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