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-1301 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
34Sp_rcontext_handler_local sp_rcontext_handler_local;
35Sp_rcontext_handler_package_body sp_rcontext_handler_package_body;
36
37sp_rcontext *Sp_rcontext_handler_local::get_rcontext(sp_rcontext *ctx) const
38{
39 return ctx;
40}
41
42sp_rcontext *Sp_rcontext_handler_package_body::get_rcontext(sp_rcontext *ctx) const
43{
44 return ctx->m_sp->m_parent->m_rcontext;
45}
46
47const LEX_CSTRING *Sp_rcontext_handler_local::get_name_prefix() const
48{
49 return &empty_clex_str;
50}
51
52const 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
65sp_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
82sp_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
91sp_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
122bool 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
139bool 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
155bool 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
177bool 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*/
197static inline bool
198check_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*/
214bool 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*/
267bool 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
327bool 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
341bool 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
394bool 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
418bool 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
428bool sp_rcontext::push_cursor(THD *thd, sp_lex_keeper *lex_keeper)
429{
430 /*
431 We should create cursors in the callers arena, as
432 it could be (and usually is) used in several instructions.
433 */
434 sp_cursor *c= new (callers_arena->mem_root) sp_cursor(thd, lex_keeper);
435
436 if (c == NULL)
437 return true;
438
439 m_cstack[m_ccount++]= c;
440 return false;
441}
442
443
444void sp_rcontext::pop_cursors(size_t count)
445{
446 DBUG_ASSERT(m_ccount >= count);
447
448 while (count--)
449 delete m_cstack[--m_ccount];
450}
451
452
453bool sp_rcontext::push_handler(sp_handler *handler, uint first_ip)
454{
455 /*
456 We should create handler entries in the callers arena, as
457 they could be (and usually are) used in several instructions.
458 */
459 sp_handler_entry *he=
460 new (callers_arena->mem_root) sp_handler_entry(handler, first_ip);
461
462 if (he == NULL)
463 return true;
464
465 return m_handlers.append(he);
466}
467
468
469void sp_rcontext::pop_handlers(size_t count)
470{
471 DBUG_ASSERT(m_handlers.elements() >= count);
472
473 for (size_t i= 0; i < count; ++i)
474 m_handlers.pop();
475}
476
477
478bool sp_rcontext::handle_sql_condition(THD *thd,
479 uint *ip,
480 const sp_instr *cur_spi)
481{
482 DBUG_ENTER("sp_rcontext::handle_sql_condition");
483
484 /*
485 If this is a fatal sub-statement error, and this runtime
486 context corresponds to a sub-statement, no CONTINUE/EXIT
487 handlers from this context are applicable: try to locate one
488 in the outer scope.
489 */
490 if (unlikely(thd->is_fatal_sub_stmt_error) && m_in_sub_stmt)
491 DBUG_RETURN(false);
492
493 Diagnostics_area *da= thd->get_stmt_da();
494 const sp_handler *found_handler= NULL;
495 const Sql_condition *found_condition= NULL;
496
497 if (unlikely(thd->is_error()))
498 {
499 found_handler=
500 cur_spi->m_ctx->find_handler(da->get_error_condition_identity());
501
502 if (found_handler)
503 found_condition= da->get_error_condition();
504
505 /*
506 Found condition can be NULL if the diagnostics area was full
507 when the error was raised. It can also be NULL if
508 Diagnostics_area::set_error_status(uint sql_error) was used.
509 In these cases, make a temporary Sql_condition here so the
510 error can be handled.
511 */
512 if (!found_condition)
513 {
514 found_condition=
515 new (callers_arena->mem_root) Sql_condition(callers_arena->mem_root,
516 da->get_error_condition_identity(),
517 da->message());
518 }
519 }
520 else if (da->current_statement_warn_count())
521 {
522 Diagnostics_area::Sql_condition_iterator it= da->sql_conditions();
523 const Sql_condition *c;
524
525 // Here we need to find the last warning/note from the stack.
526 // In MySQL most substantial warning is the last one.
527 // (We could have used a reverse iterator here if one existed)
528
529 while ((c= it++))
530 {
531 if (c->get_level() == Sql_condition::WARN_LEVEL_WARN ||
532 c->get_level() == Sql_condition::WARN_LEVEL_NOTE)
533 {
534 const sp_handler *handler= cur_spi->m_ctx->find_handler(*c);
535 if (handler)
536 {
537 found_handler= handler;
538 found_condition= c;
539 }
540 }
541 }
542 }
543
544 if (!found_handler)
545 DBUG_RETURN(false);
546
547 // At this point, we know that:
548 // - there is a pending SQL-condition (error or warning);
549 // - there is an SQL-handler for it.
550
551 DBUG_ASSERT(found_condition);
552
553 sp_handler_entry *handler_entry= NULL;
554 for (size_t i= 0; i < m_handlers.elements(); ++i)
555 {
556 sp_handler_entry *h= m_handlers.at(i);
557
558 if (h->handler == found_handler)
559 {
560 handler_entry= h;
561 break;
562 }
563 }
564
565 /*
566 handler_entry usually should not be NULL here, as that indicates
567 that the parser context thinks a HANDLER should be activated,
568 but the runtime context cannot find it.
569
570 However, this can happen (and this is in line with the Standard)
571 if SQL-condition has been raised before DECLARE HANDLER instruction
572 is processed.
573
574 For example:
575 CREATE PROCEDURE p()
576 BEGIN
577 DECLARE v INT DEFAULT 'get'; -- raises SQL-warning here
578 DECLARE EXIT HANDLER ... -- this handler does not catch the warning
579 END
580 */
581 if (!handler_entry)
582 DBUG_RETURN(false);
583
584 // Mark active conditions so that they can be deleted when the handler exits.
585 da->mark_sql_conditions_for_removal();
586
587 uint continue_ip= handler_entry->handler->type == sp_handler::CONTINUE ?
588 cur_spi->get_cont_dest() : 0;
589
590 /* End aborted result set. */
591 if (end_partial_result_set)
592 thd->protocol->end_partial_result_set(thd);
593
594 /* Reset error state. */
595 thd->clear_error();
596 thd->reset_killed(); // Some errors set thd->killed, (e.g. "bad data").
597
598 /* Add a frame to handler-call-stack. */
599 Sql_condition_info *cond_info=
600 new (callers_arena->mem_root) Sql_condition_info(found_condition,
601 callers_arena);
602 Handler_call_frame *frame=
603 new (callers_arena->mem_root) Handler_call_frame(cond_info, continue_ip);
604 m_handler_call_stack.append(frame);
605
606 *ip= handler_entry->first_ip;
607
608 DBUG_RETURN(true);
609}
610
611
612uint sp_rcontext::exit_handler(Diagnostics_area *da)
613{
614 DBUG_ENTER("sp_rcontext::exit_handler");
615 DBUG_ASSERT(m_handler_call_stack.elements() > 0);
616
617 Handler_call_frame *f= m_handler_call_stack.pop();
618
619 /*
620 Remove the SQL conditions that were present in DA when the
621 handler was activated.
622 */
623 da->remove_marked_sql_conditions();
624
625 uint continue_ip= f->continue_ip;
626
627 DBUG_RETURN(continue_ip);
628}
629
630
631int sp_rcontext::set_variable(THD *thd, uint idx, Item **value)
632{
633 DBUG_ENTER("sp_rcontext::set_variable");
634 DBUG_ASSERT(value);
635 DBUG_RETURN(thd->sp_eval_expr(m_var_table->field[idx], value));
636}
637
638
639int sp_rcontext::set_variable_row_field(THD *thd, uint var_idx, uint field_idx,
640 Item **value)
641{
642 DBUG_ENTER("sp_rcontext::set_variable_row_field");
643 DBUG_ASSERT(value);
644 Virtual_tmp_table *vtable= virtual_tmp_table_for_row(var_idx);
645 DBUG_RETURN(thd->sp_eval_expr(vtable->field[field_idx], value));
646}
647
648
649int sp_rcontext::set_variable_row_field_by_name(THD *thd, uint var_idx,
650 const LEX_CSTRING &field_name,
651 Item **value)
652{
653 DBUG_ENTER("sp_rcontext::set_variable_row_field_by_name");
654 uint field_idx;
655 if (find_row_field_by_name_or_error(&field_idx, var_idx, field_name))
656 DBUG_RETURN(1);
657 DBUG_RETURN(set_variable_row_field(thd, var_idx, field_idx, value));
658}
659
660
661int sp_rcontext::set_variable_row(THD *thd, uint var_idx, List<Item> &items)
662{
663 DBUG_ENTER("sp_rcontext::set_variable_row");
664 DBUG_ASSERT(get_variable(var_idx)->cols() == items.elements);
665 Virtual_tmp_table *vtable= virtual_tmp_table_for_row(var_idx);
666 Sp_eval_expr_state state(thd);
667 DBUG_RETURN(vtable->sp_set_all_fields_from_item_list(thd, items));
668}
669
670
671Virtual_tmp_table *sp_rcontext::virtual_tmp_table_for_row(uint var_idx)
672{
673 DBUG_ASSERT(get_variable(var_idx)->type() == Item::FIELD_ITEM);
674 DBUG_ASSERT(get_variable(var_idx)->cmp_type() == ROW_RESULT);
675 Field *field= m_var_table->field[var_idx];
676 Virtual_tmp_table **ptable= field->virtual_tmp_table_addr();
677 DBUG_ASSERT(ptable);
678 DBUG_ASSERT(ptable[0]);
679 return ptable[0];
680}
681
682
683bool sp_rcontext::find_row_field_by_name_or_error(uint *field_idx,
684 uint var_idx,
685 const LEX_CSTRING &field_name)
686{
687 Virtual_tmp_table *vtable= virtual_tmp_table_for_row(var_idx);
688 Field *row= m_var_table->field[var_idx];
689 return vtable->sp_find_field_by_name_or_error(field_idx,
690 row->field_name, field_name);
691}
692
693
694Item_cache *sp_rcontext::create_case_expr_holder(THD *thd,
695 const Item *item) const
696{
697 Item_cache *holder;
698 Query_arena current_arena;
699
700 thd->set_n_backup_active_arena(thd->spcont->callers_arena, &current_arena);
701
702 holder= item->get_cache(thd);
703
704 thd->restore_active_arena(thd->spcont->callers_arena, &current_arena);
705
706 return holder;
707}
708
709
710bool sp_rcontext::set_case_expr(THD *thd, int case_expr_id,
711 Item **case_expr_item_ptr)
712{
713 Item *case_expr_item= thd->sp_prepare_func_item(case_expr_item_ptr);
714 if (!case_expr_item)
715 return true;
716
717 if (!m_case_expr_holders[case_expr_id] ||
718 m_case_expr_holders[case_expr_id]->result_type() !=
719 case_expr_item->result_type())
720 {
721 m_case_expr_holders[case_expr_id]=
722 create_case_expr_holder(thd, case_expr_item);
723 }
724
725 m_case_expr_holders[case_expr_id]->store(case_expr_item);
726 m_case_expr_holders[case_expr_id]->cache_value();
727 return false;
728}
729
730
731///////////////////////////////////////////////////////////////////////////
732// sp_cursor implementation.
733///////////////////////////////////////////////////////////////////////////
734
735
736sp_cursor::sp_cursor(THD *thd_arg, sp_lex_keeper *lex_keeper):
737 result(thd_arg),
738 m_lex_keeper(lex_keeper),
739 server_side_cursor(NULL),
740 m_fetch_count(0),
741 m_row_count(0),
742 m_found(false)
743{
744 /*
745 currsor can't be stored in QC, so we should prevent opening QC for
746 try to write results which are absent.
747 */
748 lex_keeper->disable_query_cache();
749}
750
751
752/*
753 Open an SP cursor
754
755 SYNOPSIS
756 open()
757 THD Thread handler
758
759
760 RETURN
761 0 in case of success, -1 otherwise
762*/
763
764int sp_cursor::open(THD *thd)
765{
766 if (server_side_cursor)
767 {
768 my_message(ER_SP_CURSOR_ALREADY_OPEN,
769 ER_THD(thd, ER_SP_CURSOR_ALREADY_OPEN),
770 MYF(0));
771 return -1;
772 }
773 if (mysql_open_cursor(thd, &result, &server_side_cursor))
774 return -1;
775 return 0;
776}
777
778
779/**
780 Open the cursor, but do not copy data.
781 This method is used to fetch the cursor structure
782 to cursor%ROWTYPE routine variables.
783 Data copying is suppressed by setting thd->lex->limit_rows_examined to 0.
784*/
785int sp_cursor::open_view_structure_only(THD *thd)
786{
787 int res;
788 int thd_no_errors_save= thd->no_errors;
789 Item *limit_rows_examined= thd->lex->limit_rows_examined; // No data copying
790 if (!(thd->lex->limit_rows_examined= new (thd->mem_root) Item_uint(thd, 0)))
791 return -1;
792 thd->no_errors= true; // Suppress ER_QUERY_EXCEEDED_ROWS_EXAMINED_LIMIT
793 DBUG_ASSERT(!thd->killed);
794 res= open(thd);
795 /*
796 The query possibly exited on LIMIT ROWS EXAMINED and set thd->killed.
797 Reset it now.
798 */
799 thd->reset_killed();
800 thd->no_errors= thd_no_errors_save;
801 thd->lex->limit_rows_examined= limit_rows_examined;
802 return res;
803}
804
805
806int sp_cursor::close(THD *thd)
807{
808 if (! server_side_cursor)
809 {
810 my_message(ER_SP_CURSOR_NOT_OPEN, ER_THD(thd, ER_SP_CURSOR_NOT_OPEN),
811 MYF(0));
812 return -1;
813 }
814 m_row_count= m_fetch_count= 0;
815 m_found= false;
816 destroy();
817 return 0;
818}
819
820
821void sp_cursor::destroy()
822{
823 delete server_side_cursor;
824 server_side_cursor= NULL;
825}
826
827
828int sp_cursor::fetch(THD *thd, List<sp_variable> *vars, bool error_on_no_data)
829{
830 if (! server_side_cursor)
831 {
832 my_message(ER_SP_CURSOR_NOT_OPEN, ER_THD(thd, ER_SP_CURSOR_NOT_OPEN),
833 MYF(0));
834 return -1;
835 }
836 if (vars->elements != result.get_field_count() &&
837 (vars->elements != 1 ||
838 result.get_field_count() !=
839 thd->spcont->get_variable(vars->head()->offset)->cols()))
840 {
841 my_message(ER_SP_WRONG_NO_OF_FETCH_ARGS,
842 ER_THD(thd, ER_SP_WRONG_NO_OF_FETCH_ARGS), MYF(0));
843 return -1;
844 }
845
846 m_fetch_count++;
847 DBUG_EXECUTE_IF("bug23032_emit_warning",
848 push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
849 ER_UNKNOWN_ERROR,
850 ER_THD(thd, ER_UNKNOWN_ERROR)););
851
852 result.set_spvar_list(vars);
853
854 /* Attempt to fetch one row */
855 if (server_side_cursor->is_open())
856 server_side_cursor->fetch(1);
857
858 /*
859 If the cursor was pointing after the last row, the fetch will
860 close it instead of sending any rows.
861 */
862 if (! server_side_cursor->is_open())
863 {
864 m_found= false;
865 if (!error_on_no_data)
866 return 0;
867 my_message(ER_SP_FETCH_NO_DATA, ER_THD(thd, ER_SP_FETCH_NO_DATA), MYF(0));
868 return -1;
869 }
870
871 m_found= true;
872 m_row_count++;
873 return 0;
874}
875
876
877bool sp_cursor::export_structure(THD *thd, Row_definition_list *list)
878{
879 return server_side_cursor->export_structure(thd, list);
880}
881
882///////////////////////////////////////////////////////////////////////////
883// sp_cursor::Select_fetch_into_spvars implementation.
884///////////////////////////////////////////////////////////////////////////
885
886
887int sp_cursor::Select_fetch_into_spvars::prepare(List<Item> &fields,
888 SELECT_LEX_UNIT *u)
889{
890 /*
891 Cache the number of columns in the result set in order to easily
892 return an error if column count does not match value count.
893 */
894 field_count= fields.elements;
895 return select_result_interceptor::prepare(fields, u);
896}
897
898
899bool sp_cursor::Select_fetch_into_spvars::
900 send_data_to_variable_list(List<sp_variable> &vars, List<Item> &items)
901{
902 List_iterator_fast<sp_variable> spvar_iter(vars);
903 List_iterator_fast<Item> item_iter(items);
904 sp_variable *spvar;
905 Item *item;
906
907 /* Must be ensured by the caller */
908 DBUG_ASSERT(vars.elements == items.elements);
909
910 /*
911 Assign the row fetched from a server side cursor to stored
912 procedure variables.
913 */
914 for (; spvar= spvar_iter++, item= item_iter++; )
915 {
916 if (thd->spcont->set_variable(thd, spvar->offset, &item))
917 return true;
918 }
919 return false;
920}
921
922
923int sp_cursor::Select_fetch_into_spvars::send_data(List<Item> &items)
924{
925 Item *item;
926 /*
927 If we have only one variable in spvar_list, and this is a ROW variable,
928 and the number of fields in the ROW variable matches the number of
929 fields in the query result, we fetch to this ROW variable.
930
931 If there is one variable, and it is a ROW variable, but its number
932 of fields does not match the number of fields in the query result,
933 we go through send_data_to_variable_list(). It will report an error
934 on attempt to assign a scalar value to a ROW variable.
935 */
936 return spvar_list->elements == 1 &&
937 (item= thd->spcont->get_variable(spvar_list->head()->offset)) &&
938 item->type_handler() == &type_handler_row &&
939 item->cols() == items.elements ?
940 thd->spcont->set_variable_row(thd, spvar_list->head()->offset, items) :
941 send_data_to_variable_list(*spvar_list, items);
942}
943