1 /* Copyright (c) 2002, 2010, 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-1335  USA */
15 
16 #include "mariadb.h"
17 #include "sql_priv.h"
18 #include "unireg.h"
19 #ifdef USE_PRAGMA_IMPLEMENTATION
20 #pragma implementation
21 #endif
22 
23 #include "mysql.h"
24 #include "sp_head.h"
25 #include "sql_cursor.h"
26 #include "sp_rcontext.h"
27 #include "sp_pcontext.h"
28 #include "sql_select.h"                     // create_virtual_tmp_table
29 #include "sql_base.h"                       // open_tables_only_view_structure
30 #include "sql_acl.h"                        // SELECT_ACL
31 #include "sql_parse.h"                      // check_table_access
32 
33 
34 Sp_rcontext_handler_local sp_rcontext_handler_local;
35 Sp_rcontext_handler_package_body sp_rcontext_handler_package_body;
36 
get_rcontext(sp_rcontext * ctx) const37 sp_rcontext *Sp_rcontext_handler_local::get_rcontext(sp_rcontext *ctx) const
38 {
39   return ctx;
40 }
41 
get_rcontext(sp_rcontext * ctx) const42 sp_rcontext *Sp_rcontext_handler_package_body::get_rcontext(sp_rcontext *ctx) const
43 {
44   return ctx->m_sp->m_parent->m_rcontext;
45 }
46 
get_name_prefix() const47 const LEX_CSTRING *Sp_rcontext_handler_local::get_name_prefix() const
48 {
49   return &empty_clex_str;
50 }
51 
get_name_prefix() const52 const LEX_CSTRING *Sp_rcontext_handler_package_body::get_name_prefix() const
53 {
54   static const LEX_CSTRING sp_package_body_variable_prefix_clex_str=
55                            {STRING_WITH_LEN("PACKAGE_BODY.")};
56   return &sp_package_body_variable_prefix_clex_str;
57 }
58 
59 
60 ///////////////////////////////////////////////////////////////////////////
61 // sp_rcontext implementation.
62 ///////////////////////////////////////////////////////////////////////////
63 
64 
sp_rcontext(const sp_head * owner,const sp_pcontext * root_parsing_ctx,Field * return_value_fld,bool in_sub_stmt)65 sp_rcontext::sp_rcontext(const sp_head *owner,
66                          const sp_pcontext *root_parsing_ctx,
67                          Field *return_value_fld,
68                          bool in_sub_stmt)
69   :end_partial_result_set(false),
70    pause_state(false), quit_func(false), instr_ptr(0),
71    m_sp(owner),
72    m_root_parsing_ctx(root_parsing_ctx),
73    m_var_table(NULL),
74    m_return_value_fld(return_value_fld),
75    m_return_value_set(false),
76    m_in_sub_stmt(in_sub_stmt),
77    m_handlers(PSI_INSTRUMENT_MEM), m_handler_call_stack(PSI_INSTRUMENT_MEM),
78    m_ccount(0)
79 {
80 }
81 
82 
~sp_rcontext()83 sp_rcontext::~sp_rcontext()
84 {
85   delete m_var_table;
86   // Leave m_handlers, m_handler_call_stack, m_var_items, m_cstack
87   // and m_case_expr_holders untouched.
88   // They are allocated in mem roots and will be freed accordingly.
89 }
90 
91 
create(THD * thd,const sp_head * owner,const sp_pcontext * root_parsing_ctx,Field * return_value_fld,Row_definition_list & field_def_lst)92 sp_rcontext *sp_rcontext::create(THD *thd,
93                                  const sp_head *owner,
94                                  const sp_pcontext *root_parsing_ctx,
95                                  Field *return_value_fld,
96                                  Row_definition_list &field_def_lst)
97 {
98   SELECT_LEX *save_current_select;
99   sp_rcontext *ctx= new (thd->mem_root) sp_rcontext(owner,
100                                                     root_parsing_ctx,
101                                                     return_value_fld,
102                                                     thd->in_sub_stmt);
103   if (!ctx)
104     return NULL;
105 
106   /* Reset current_select as it's checked in Item_ident::Item_ident */
107   save_current_select= thd->lex->current_select;
108   thd->lex->current_select= 0;
109 
110   if (ctx->alloc_arrays(thd) ||
111       ctx->init_var_table(thd, field_def_lst) ||
112       ctx->init_var_items(thd, field_def_lst))
113   {
114     delete ctx;
115     ctx= 0;
116   }
117 
118   thd->lex->current_select= save_current_select;
119   return ctx;
120 }
121 
122 
append_uniq(MEM_ROOT * mem_root,Spvar_definition * var)123 bool Row_definition_list::append_uniq(MEM_ROOT *mem_root, Spvar_definition *var)
124 {
125   DBUG_ASSERT(elements);
126   uint unused;
127   if (unlikely(find_row_field_by_name(&var->field_name, &unused)))
128   {
129     my_error(ER_DUP_FIELDNAME, MYF(0), var->field_name.str);
130     return true;
131   }
132   return push_back(var, mem_root);
133 }
134 
135 
136 bool Row_definition_list::
adjust_formal_params_to_actual_params(THD * thd,List<Item> * args)137        adjust_formal_params_to_actual_params(THD *thd, List<Item> *args)
138 {
139   List_iterator<Spvar_definition> it(*this);
140   List_iterator<Item> it_args(*args);
141   DBUG_ASSERT(elements >= args->elements );
142   Spvar_definition *def;
143   Item *arg;
144   while ((def= it++) && (arg= it_args++))
145   {
146     if (def->type_handler()->adjust_spparam_type(def, arg))
147       return true;
148   }
149   return false;
150 }
151 
152 
153 bool Row_definition_list::
adjust_formal_params_to_actual_params(THD * thd,Item ** args,uint arg_count)154        adjust_formal_params_to_actual_params(THD *thd,
155                                              Item **args, uint arg_count)
156 {
157   List_iterator<Spvar_definition> it(*this);
158   DBUG_ASSERT(elements >= arg_count );
159   Spvar_definition *def;
160   for (uint i= 0; (def= it++) && (i < arg_count) ; i++)
161   {
162     if (def->type_handler()->adjust_spparam_type(def, args[i]))
163       return true;
164   }
165   return false;
166 }
167 
168 
alloc_arrays(THD * thd)169 bool sp_rcontext::alloc_arrays(THD *thd)
170 {
171   {
172     size_t n= m_root_parsing_ctx->max_cursor_index();
173     m_cstack.reset(
174       static_cast<sp_cursor **> (
175         thd->alloc(n * sizeof (sp_cursor*))),
176       n);
177   }
178 
179   {
180     size_t n= m_root_parsing_ctx->get_num_case_exprs();
181     m_case_expr_holders.reset(
182       static_cast<Item_cache **> (
183         thd->calloc(n * sizeof (Item_cache*))),
184       n);
185   }
186 
187   return !m_cstack.array() || !m_case_expr_holders.array();
188 }
189 
190 
init_var_table(THD * thd,List<Spvar_definition> & field_def_lst)191 bool sp_rcontext::init_var_table(THD *thd,
192                                  List<Spvar_definition> &field_def_lst)
193 {
194   if (!m_root_parsing_ctx->max_var_index())
195     return false;
196 
197   DBUG_ASSERT(field_def_lst.elements == m_root_parsing_ctx->max_var_index());
198 
199   if (!(m_var_table= create_virtual_tmp_table(thd, field_def_lst)))
200     return true;
201 
202   return false;
203 }
204 
205 
206 /**
207   Check if we have access to use a column as a %TYPE reference.
208   @return false - OK
209   @return true  - access denied
210 */
211 static inline bool
check_column_grant_for_type_ref(THD * thd,TABLE_LIST * table_list,const char * str,size_t length,Field * fld)212 check_column_grant_for_type_ref(THD *thd, TABLE_LIST *table_list,
213                                 const char *str, size_t length,
214                                 Field *fld)
215 {
216 #ifndef NO_EMBEDDED_ACCESS_CHECKS
217   table_list->table->grant.want_privilege= SELECT_ACL;
218   return check_column_grant_in_table_ref(thd, table_list, str, length, fld);
219 #else
220   return false;
221 #endif
222 }
223 
224 
225 /**
226   This method implementation is very close to fill_schema_table_by_open().
227 */
resolve_type_ref(THD * thd,Column_definition * def)228 bool Qualified_column_ident::resolve_type_ref(THD *thd, Column_definition *def)
229 {
230   Open_tables_backup open_tables_state_backup;
231   thd->reset_n_backup_open_tables_state(&open_tables_state_backup);
232 
233   TABLE_LIST *table_list;
234   Field *src;
235   LEX *save_lex= thd->lex;
236   bool rc= true;
237 
238   sp_lex_local lex(thd, thd->lex);
239   thd->lex= &lex;
240 
241   lex.context_analysis_only= CONTEXT_ANALYSIS_ONLY_VIEW;
242   // Make %TYPE variables see temporary tables that shadow permanent tables
243   thd->temporary_tables= open_tables_state_backup.temporary_tables;
244 
245   if ((table_list=
246          lex.first_select_lex()->add_table_to_list(thd, this, NULL, 0,
247                                                    TL_READ_NO_INSERT,
248                                                    MDL_SHARED_READ)) &&
249       !check_table_access(thd, SELECT_ACL, table_list, TRUE, UINT_MAX, FALSE) &&
250       !open_tables_only_view_structure(thd, table_list,
251                                        thd->mdl_context.has_locks()))
252   {
253     if (likely((src= lex.query_tables->table->find_field_by_name(&m_column))))
254     {
255       if (!(rc= check_column_grant_for_type_ref(thd, table_list,
256                                                 m_column.str,
257                                                 m_column.length, src)))
258       {
259         *def= Column_definition(thd, src, NULL/*No defaults,no constraints*/);
260         def->flags&= (uint) ~NOT_NULL_FLAG;
261         rc= def->sp_prepare_create_field(thd, thd->mem_root);
262       }
263     }
264     else
265       my_error(ER_BAD_FIELD_ERROR, MYF(0), m_column.str, table.str);
266   }
267 
268   lex.unit.cleanup();
269   thd->temporary_tables= NULL; // Avoid closing temporary tables
270   close_thread_tables(thd);
271   thd->lex= save_lex;
272   thd->restore_backup_open_tables_state(&open_tables_state_backup);
273   return rc;
274 }
275 
276 
277 /**
278   This method resolves the structure of a variable declared as:
279      rec t1%ROWTYPE;
280   It opens the table "t1" and copies its structure to %ROWTYPE variable.
281 */
resolve_table_rowtype_ref(THD * thd,Row_definition_list & defs)282 bool Table_ident::resolve_table_rowtype_ref(THD *thd,
283                                             Row_definition_list &defs)
284 {
285   Open_tables_backup open_tables_state_backup;
286   thd->reset_n_backup_open_tables_state(&open_tables_state_backup);
287 
288   TABLE_LIST *table_list;
289   LEX *save_lex= thd->lex;
290   bool rc= true;
291 
292   /*
293     Create a temporary LEX on stack and switch to it.
294     In case of VIEW, open_tables_only_view_structure() will open more
295     tables/views recursively. We want to avoid them to stick to the current LEX.
296   */
297   sp_lex_local lex(thd, thd->lex);
298   thd->lex= &lex;
299 
300   lex.context_analysis_only= CONTEXT_ANALYSIS_ONLY_VIEW;
301   // Make %ROWTYPE variables see temporary tables that shadow permanent tables
302   thd->temporary_tables= open_tables_state_backup.temporary_tables;
303 
304   if ((table_list=
305          lex.first_select_lex()->add_table_to_list(thd, this, NULL, 0,
306                                                    TL_READ_NO_INSERT,
307                                                    MDL_SHARED_READ)) &&
308       !check_table_access(thd, SELECT_ACL, table_list, TRUE, UINT_MAX, FALSE) &&
309       !open_tables_only_view_structure(thd, table_list,
310                                        thd->mdl_context.has_locks()))
311   {
312     for (Field **src= lex.query_tables->table->field; *src; src++)
313     {
314       /*
315          Make field names on the THD memory root,
316          as the table will be closed and freed soon,
317          in the end of this method.
318       */
319       LEX_CSTRING tmp= src[0]->field_name;
320       Spvar_definition *def;
321       if ((rc= check_column_grant_for_type_ref(thd, table_list,
322                                                tmp.str, tmp.length,src[0])) ||
323           (rc= !(src[0]->field_name.str= thd->strmake(tmp.str, tmp.length))) ||
324           (rc= !(def= new (thd->mem_root) Spvar_definition(thd, *src))))
325         break;
326       src[0]->field_name.str= tmp.str; // Restore field name, just in case.
327       def->flags&= (uint) ~NOT_NULL_FLAG;
328       if ((rc= def->sp_prepare_create_field(thd, thd->mem_root)))
329         break;
330       defs.push_back(def, thd->mem_root);
331     }
332   }
333 
334   lex.unit.cleanup();
335   thd->temporary_tables= NULL; // Avoid closing temporary tables
336   close_thread_tables(thd);
337   thd->lex= save_lex;
338   thd->restore_backup_open_tables_state(&open_tables_state_backup);
339   return rc;
340 }
341 
342 
resolve_type_refs(THD * thd)343 bool Row_definition_list::resolve_type_refs(THD *thd)
344 {
345   List_iterator<Spvar_definition> it(*this);
346   Spvar_definition *def;
347   while ((def= it++))
348   {
349     if (def->is_column_type_ref() &&
350         def->column_type_ref()->resolve_type_ref(thd, def))
351       return true;
352   }
353   return false;
354 };
355 
356 
init_var_items(THD * thd,List<Spvar_definition> & field_def_lst)357 bool sp_rcontext::init_var_items(THD *thd,
358                                  List<Spvar_definition> &field_def_lst)
359 {
360   uint num_vars= m_root_parsing_ctx->max_var_index();
361 
362   m_var_items.reset(
363     static_cast<Item_field **> (
364       thd->alloc(num_vars * sizeof (Item *))),
365     num_vars);
366 
367   if (!m_var_items.array())
368     return true;
369 
370   DBUG_ASSERT(field_def_lst.elements == num_vars);
371   List_iterator<Spvar_definition> it(field_def_lst);
372   Spvar_definition *def= it++;
373 
374   for (uint idx= 0; idx < num_vars; ++idx, def= it++)
375   {
376     Field *field= m_var_table->field[idx];
377     if (def->is_table_rowtype_ref())
378     {
379       Row_definition_list defs;
380       Item_field_row *item= new (thd->mem_root) Item_field_row(thd, field);
381       if (!(m_var_items[idx]= item) ||
382           def->table_rowtype_ref()->resolve_table_rowtype_ref(thd, defs) ||
383           item->row_create_items(thd, &defs))
384         return true;
385     }
386     else if (def->is_cursor_rowtype_ref())
387     {
388       Row_definition_list defs;
389       Item_field_row *item= new (thd->mem_root) Item_field_row(thd, field);
390       if (!(m_var_items[idx]= item))
391         return true;
392     }
393     else if (def->is_row())
394     {
395       Item_field_row *item= new (thd->mem_root) Item_field_row(thd, field);
396       if (!(m_var_items[idx]= item) ||
397           item->row_create_items(thd, def->row_field_definitions()))
398         return true;
399     }
400     else
401     {
402       if (!(m_var_items[idx]= new (thd->mem_root) Item_field(thd, field)))
403         return true;
404     }
405   }
406   return false;
407 }
408 
409 
row_create_items(THD * thd,List<Spvar_definition> * list)410 bool Item_field_row::row_create_items(THD *thd, List<Spvar_definition> *list)
411 {
412   DBUG_ASSERT(list);
413   DBUG_ASSERT(field);
414   Virtual_tmp_table **ptable= field->virtual_tmp_table_addr();
415   DBUG_ASSERT(ptable);
416   if (!(ptable[0]= create_virtual_tmp_table(thd, *list)))
417     return true;
418 
419   if (alloc_arguments(thd, list->elements))
420     return true;
421 
422   List_iterator<Spvar_definition> it(*list);
423   Spvar_definition *def;
424   for (arg_count= 0; (def= it++); arg_count++)
425   {
426     if (!(args[arg_count]= new (thd->mem_root)
427                            Item_field(thd, ptable[0]->field[arg_count])))
428       return true;
429   }
430   return false;
431 }
432 
433 
set_return_value(THD * thd,Item ** return_value_item)434 bool sp_rcontext::set_return_value(THD *thd, Item **return_value_item)
435 {
436   DBUG_ASSERT(m_return_value_fld);
437 
438   m_return_value_set = true;
439 
440   return thd->sp_eval_expr(m_return_value_fld, return_value_item);
441 }
442 
443 
push_cursor(sp_cursor * c)444 void sp_rcontext::push_cursor(sp_cursor *c)
445 {
446   m_cstack[m_ccount++]= c;
447 }
448 
449 
pop_cursor(THD * thd)450 void sp_rcontext::pop_cursor(THD *thd)
451 {
452   DBUG_ASSERT(m_ccount > 0);
453   if (m_cstack[m_ccount - 1]->is_open())
454     m_cstack[m_ccount - 1]->close(thd);
455   m_ccount--;
456 }
457 
458 
pop_cursors(THD * thd,size_t count)459 void sp_rcontext::pop_cursors(THD *thd, size_t count)
460 {
461   DBUG_ASSERT(m_ccount >= count);
462   while (count--)
463     pop_cursor(thd);
464 }
465 
466 
push_handler(sp_instr_hpush_jump * entry)467 bool sp_rcontext::push_handler(sp_instr_hpush_jump *entry)
468 {
469   return m_handlers.append(entry);
470 }
471 
472 
pop_handlers(size_t count)473 void sp_rcontext::pop_handlers(size_t count)
474 {
475   DBUG_ASSERT(m_handlers.elements() >= count);
476 
477   for (size_t i= 0; i < count; ++i)
478     m_handlers.pop();
479 }
480 
481 
handle_sql_condition(THD * thd,uint * ip,const sp_instr * cur_spi)482 bool sp_rcontext::handle_sql_condition(THD *thd,
483                                        uint *ip,
484                                        const sp_instr *cur_spi)
485 {
486   DBUG_ENTER("sp_rcontext::handle_sql_condition");
487 
488   /*
489     If this is a fatal sub-statement error, and this runtime
490     context corresponds to a sub-statement, no CONTINUE/EXIT
491     handlers from this context are applicable: try to locate one
492     in the outer scope.
493   */
494   if (unlikely(thd->is_fatal_sub_stmt_error) && m_in_sub_stmt)
495     DBUG_RETURN(false);
496 
497   Diagnostics_area *da= thd->get_stmt_da();
498   const sp_handler *found_handler= NULL;
499   const Sql_condition *found_condition= NULL;
500 
501   if (unlikely(thd->is_error()))
502   {
503     found_handler=
504       cur_spi->m_ctx->find_handler(da->get_error_condition_identity());
505 
506     if (found_handler)
507       found_condition= da->get_error_condition();
508 
509     /*
510       Found condition can be NULL if the diagnostics area was full
511       when the error was raised. It can also be NULL if
512       Diagnostics_area::set_error_status(uint sql_error) was used.
513       In these cases, make a temporary Sql_condition here so the
514       error can be handled.
515     */
516     if (!found_condition)
517     {
518       found_condition=
519         new (callers_arena->mem_root) Sql_condition(callers_arena->mem_root,
520                                                     da->get_error_condition_identity(),
521                                                     da->message());
522     }
523   }
524   else if (da->current_statement_warn_count())
525   {
526     Diagnostics_area::Sql_condition_iterator it= da->sql_conditions();
527     const Sql_condition *c;
528 
529     // Here we need to find the last warning/note from the stack.
530     // In MySQL most substantial warning is the last one.
531     // (We could have used a reverse iterator here if one existed)
532 
533     while ((c= it++))
534     {
535       if (c->get_level() == Sql_condition::WARN_LEVEL_WARN ||
536           c->get_level() == Sql_condition::WARN_LEVEL_NOTE)
537       {
538         const sp_handler *handler= cur_spi->m_ctx->find_handler(*c);
539         if (handler)
540         {
541           found_handler= handler;
542           found_condition= c;
543         }
544       }
545     }
546   }
547 
548   if (!found_handler)
549     DBUG_RETURN(false);
550 
551   // At this point, we know that:
552   //  - there is a pending SQL-condition (error or warning);
553   //  - there is an SQL-handler for it.
554 
555   DBUG_ASSERT(found_condition);
556 
557   sp_instr_hpush_jump *handler_entry= NULL;
558   for (size_t i= 0; i < m_handlers.elements(); ++i)
559   {
560     sp_instr_hpush_jump *h= m_handlers.at(i);
561 
562     if (h->get_handler() == found_handler)
563     {
564       handler_entry= h;
565       break;
566     }
567   }
568 
569   /*
570     handler_entry usually should not be NULL here, as that indicates
571     that the parser context thinks a HANDLER should be activated,
572     but the runtime context cannot find it.
573 
574     However, this can happen (and this is in line with the Standard)
575     if SQL-condition has been raised before DECLARE HANDLER instruction
576     is processed.
577 
578     For example:
579     CREATE PROCEDURE p()
580     BEGIN
581       DECLARE v INT DEFAULT 'get'; -- raises SQL-warning here
582       DECLARE EXIT HANDLER ...     -- this handler does not catch the warning
583     END
584   */
585   if (!handler_entry)
586     DBUG_RETURN(false);
587 
588   // Mark active conditions so that they can be deleted when the handler exits.
589   da->mark_sql_conditions_for_removal();
590 
591   uint continue_ip= handler_entry->get_handler()->type == sp_handler::CONTINUE ?
592     cur_spi->get_cont_dest() : 0;
593 
594   /* End aborted result set. */
595   if (end_partial_result_set)
596     thd->protocol->end_partial_result_set(thd);
597 
598   /* Reset error state. */
599   thd->clear_error();
600   thd->reset_killed();      // Some errors set thd->killed, (e.g. "bad data").
601 
602   /* Add a frame to handler-call-stack. */
603   Sql_condition_info *cond_info=
604     new (callers_arena->mem_root) Sql_condition_info(found_condition,
605                                                      callers_arena);
606   Handler_call_frame *frame=
607     new (callers_arena->mem_root) Handler_call_frame(cond_info, continue_ip);
608   m_handler_call_stack.append(frame);
609 
610   *ip= handler_entry->m_ip + 1;
611 
612   DBUG_RETURN(true);
613 }
614 
615 
exit_handler(Diagnostics_area * da)616 uint sp_rcontext::exit_handler(Diagnostics_area *da)
617 {
618   DBUG_ENTER("sp_rcontext::exit_handler");
619   DBUG_ASSERT(m_handler_call_stack.elements() > 0);
620 
621   Handler_call_frame *f= m_handler_call_stack.pop();
622 
623   /*
624     Remove the SQL conditions that were present in DA when the
625     handler was activated.
626   */
627   da->remove_marked_sql_conditions();
628 
629   uint continue_ip= f->continue_ip;
630 
631   DBUG_RETURN(continue_ip);
632 }
633 
634 
set_variable(THD * thd,uint idx,Item ** value)635 int sp_rcontext::set_variable(THD *thd, uint idx, Item **value)
636 {
637   DBUG_ENTER("sp_rcontext::set_variable");
638   DBUG_ASSERT(value);
639   DBUG_RETURN(thd->sp_eval_expr(m_var_table->field[idx], value));
640 }
641 
642 
set_variable_row_field(THD * thd,uint var_idx,uint field_idx,Item ** value)643 int sp_rcontext::set_variable_row_field(THD *thd, uint var_idx, uint field_idx,
644                                         Item **value)
645 {
646   DBUG_ENTER("sp_rcontext::set_variable_row_field");
647   DBUG_ASSERT(value);
648   Virtual_tmp_table *vtable= virtual_tmp_table_for_row(var_idx);
649   DBUG_RETURN(thd->sp_eval_expr(vtable->field[field_idx], value));
650 }
651 
652 
set_variable_row_field_by_name(THD * thd,uint var_idx,const LEX_CSTRING & field_name,Item ** value)653 int sp_rcontext::set_variable_row_field_by_name(THD *thd, uint var_idx,
654                                                 const LEX_CSTRING &field_name,
655                                                 Item **value)
656 {
657   DBUG_ENTER("sp_rcontext::set_variable_row_field_by_name");
658   uint field_idx;
659   if (find_row_field_by_name_or_error(&field_idx, var_idx, field_name))
660     DBUG_RETURN(1);
661   DBUG_RETURN(set_variable_row_field(thd, var_idx, field_idx, value));
662 }
663 
664 
set_variable_row(THD * thd,uint var_idx,List<Item> & items)665 int sp_rcontext::set_variable_row(THD *thd, uint var_idx, List<Item> &items)
666 {
667   DBUG_ENTER("sp_rcontext::set_variable_row");
668   DBUG_ASSERT(get_variable(var_idx)->cols() == items.elements);
669   Virtual_tmp_table *vtable= virtual_tmp_table_for_row(var_idx);
670   Sp_eval_expr_state state(thd);
671   DBUG_RETURN(vtable->sp_set_all_fields_from_item_list(thd, items));
672 }
673 
674 
virtual_tmp_table_for_row(uint var_idx)675 Virtual_tmp_table *sp_rcontext::virtual_tmp_table_for_row(uint var_idx)
676 {
677   DBUG_ASSERT(get_variable(var_idx)->type() == Item::FIELD_ITEM);
678   DBUG_ASSERT(get_variable(var_idx)->cmp_type() == ROW_RESULT);
679   Field *field= m_var_table->field[var_idx];
680   Virtual_tmp_table **ptable= field->virtual_tmp_table_addr();
681   DBUG_ASSERT(ptable);
682   DBUG_ASSERT(ptable[0]);
683   return ptable[0];
684 }
685 
686 
find_row_field_by_name_or_error(uint * field_idx,uint var_idx,const LEX_CSTRING & field_name)687 bool sp_rcontext::find_row_field_by_name_or_error(uint *field_idx,
688                                                   uint var_idx,
689                                                   const LEX_CSTRING &field_name)
690 {
691   Virtual_tmp_table *vtable= virtual_tmp_table_for_row(var_idx);
692   Field *row= m_var_table->field[var_idx];
693   return vtable->sp_find_field_by_name_or_error(field_idx,
694                                                 row->field_name, field_name);
695 }
696 
697 
create_case_expr_holder(THD * thd,const Item * item) const698 Item_cache *sp_rcontext::create_case_expr_holder(THD *thd,
699                                                  const Item *item) const
700 {
701   Item_cache *holder;
702   Query_arena current_arena;
703 
704   thd->set_n_backup_active_arena(thd->spcont->callers_arena, &current_arena);
705 
706   holder= item->get_cache(thd);
707 
708   thd->restore_active_arena(thd->spcont->callers_arena, &current_arena);
709 
710   return holder;
711 }
712 
713 
set_case_expr(THD * thd,int case_expr_id,Item ** case_expr_item_ptr)714 bool sp_rcontext::set_case_expr(THD *thd, int case_expr_id,
715                                 Item **case_expr_item_ptr)
716 {
717   Item *case_expr_item= thd->sp_prepare_func_item(case_expr_item_ptr);
718   if (!case_expr_item)
719     return true;
720 
721   if (!m_case_expr_holders[case_expr_id] ||
722       m_case_expr_holders[case_expr_id]->result_type() !=
723         case_expr_item->result_type())
724   {
725     m_case_expr_holders[case_expr_id]=
726       create_case_expr_holder(thd, case_expr_item);
727   }
728 
729   m_case_expr_holders[case_expr_id]->store(case_expr_item);
730   m_case_expr_holders[case_expr_id]->cache_value();
731   return false;
732 }
733 
734 
735 ///////////////////////////////////////////////////////////////////////////
736 // sp_cursor implementation.
737 ///////////////////////////////////////////////////////////////////////////
738 
739 
740 /*
741   Open an SP cursor
742 
743   SYNOPSIS
744     open()
745     THD		         Thread handler
746 
747 
748   RETURN
749    0 in case of success, -1 otherwise
750 */
751 
open(THD * thd)752 int sp_cursor::open(THD *thd)
753 {
754   if (server_side_cursor)
755   {
756     my_message(ER_SP_CURSOR_ALREADY_OPEN,
757                ER_THD(thd, ER_SP_CURSOR_ALREADY_OPEN),
758                MYF(0));
759     return -1;
760   }
761   if (mysql_open_cursor(thd, &result, &server_side_cursor))
762     return -1;
763   return 0;
764 }
765 
766 
close(THD * thd)767 int sp_cursor::close(THD *thd)
768 {
769   if (! server_side_cursor)
770   {
771     my_message(ER_SP_CURSOR_NOT_OPEN, ER_THD(thd, ER_SP_CURSOR_NOT_OPEN),
772                MYF(0));
773     return -1;
774   }
775   sp_cursor_statistics::reset();
776   destroy();
777   return 0;
778 }
779 
780 
destroy()781 void sp_cursor::destroy()
782 {
783   delete server_side_cursor;
784   server_side_cursor= NULL;
785 }
786 
787 
fetch(THD * thd,List<sp_variable> * vars,bool error_on_no_data)788 int sp_cursor::fetch(THD *thd, List<sp_variable> *vars, bool error_on_no_data)
789 {
790   if (! server_side_cursor)
791   {
792     my_message(ER_SP_CURSOR_NOT_OPEN, ER_THD(thd, ER_SP_CURSOR_NOT_OPEN),
793                MYF(0));
794     return -1;
795   }
796   if (vars->elements != result.get_field_count() &&
797       (vars->elements != 1 ||
798        result.get_field_count() !=
799        thd->spcont->get_variable(vars->head()->offset)->cols()))
800   {
801     my_message(ER_SP_WRONG_NO_OF_FETCH_ARGS,
802                ER_THD(thd, ER_SP_WRONG_NO_OF_FETCH_ARGS), MYF(0));
803     return -1;
804   }
805 
806   m_fetch_count++;
807   DBUG_EXECUTE_IF("bug23032_emit_warning",
808                   push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
809                                ER_UNKNOWN_ERROR,
810                                ER_THD(thd, ER_UNKNOWN_ERROR)););
811 
812   result.set_spvar_list(vars);
813 
814   DBUG_ASSERT(!thd->is_error());
815 
816   /* Attempt to fetch one row */
817   if (server_side_cursor->is_open())
818   {
819     server_side_cursor->fetch(1);
820     if (thd->is_error())
821       return -1; // e.g. data type conversion failed
822   }
823 
824   /*
825     If the cursor was pointing after the last row, the fetch will
826     close it instead of sending any rows.
827   */
828   if (! server_side_cursor->is_open())
829   {
830     m_found= false;
831     if (!error_on_no_data)
832       return 0;
833     my_message(ER_SP_FETCH_NO_DATA, ER_THD(thd, ER_SP_FETCH_NO_DATA), MYF(0));
834     return -1;
835   }
836 
837   m_found= true;
838   m_row_count++;
839   return 0;
840 }
841 
842 
export_structure(THD * thd,Row_definition_list * list)843 bool sp_cursor::export_structure(THD *thd, Row_definition_list *list)
844 {
845   return server_side_cursor->export_structure(thd, list);
846 }
847 
848 ///////////////////////////////////////////////////////////////////////////
849 // sp_cursor::Select_fetch_into_spvars implementation.
850 ///////////////////////////////////////////////////////////////////////////
851 
852 
prepare(List<Item> & fields,SELECT_LEX_UNIT * u)853 int sp_cursor::Select_fetch_into_spvars::prepare(List<Item> &fields,
854                                                  SELECT_LEX_UNIT *u)
855 {
856   /*
857     Cache the number of columns in the result set in order to easily
858     return an error if column count does not match value count.
859   */
860   field_count= fields.elements;
861   return select_result_interceptor::prepare(fields, u);
862 }
863 
864 
865 bool sp_cursor::Select_fetch_into_spvars::
send_data_to_variable_list(List<sp_variable> & vars,List<Item> & items)866        send_data_to_variable_list(List<sp_variable> &vars, List<Item> &items)
867 {
868   List_iterator_fast<sp_variable> spvar_iter(vars);
869   List_iterator_fast<Item> item_iter(items);
870   sp_variable *spvar;
871   Item *item;
872 
873   /* Must be ensured by the caller */
874   DBUG_ASSERT(vars.elements == items.elements);
875 
876   /*
877     Assign the row fetched from a server side cursor to stored
878     procedure variables.
879   */
880   for (; spvar= spvar_iter++, item= item_iter++; )
881   {
882     if (thd->spcont->set_variable(thd, spvar->offset, &item))
883       return true;
884   }
885   return false;
886 }
887 
888 
send_data(List<Item> & items)889 int sp_cursor::Select_fetch_into_spvars::send_data(List<Item> &items)
890 {
891   Item *item;
892   /*
893     If we have only one variable in spvar_list, and this is a ROW variable,
894     and the number of fields in the ROW variable matches the number of
895     fields in the query result, we fetch to this ROW variable.
896 
897     If there is one variable, and it is a ROW variable, but its number
898     of fields does not match the number of fields in the query result,
899     we go through send_data_to_variable_list(). It will report an error
900     on attempt to assign a scalar value to a ROW variable.
901   */
902   return spvar_list->elements == 1 &&
903          (item= thd->spcont->get_variable(spvar_list->head()->offset)) &&
904          item->type_handler() == &type_handler_row &&
905          item->cols() == items.elements ?
906     thd->spcont->set_variable_row(thd, spvar_list->head()->offset, items) :
907     send_data_to_variable_list(*spvar_list, items);
908 }
909