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, ¤t_arena);
705
706 holder= item->get_cache(thd);
707
708 thd->restore_active_arena(thd->spcont->callers_arena, ¤t_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