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 "sp_pcontext.h"
24 #include "sp_head.h"
25 
26 bool sp_condition_value::equals(const sp_condition_value *cv) const
27 {
28   DBUG_ASSERT(cv);
29 
30   /*
31     The following test disallows duplicate handlers,
32     including user defined exceptions with the same WHEN clause:
33       DECLARE
34         a EXCEPTION;
35         b EXCEPTION;
36       BEGIN
37         RAUSE a;
38       EXCEPTION
39         WHEN a THEN RETURN 'a0';
40         WHEN a THEN RETURN 'a1';
41       END
42   */
43   if (this == cv)
44     return true;
45 
46   /*
47     The test below considers two conditions of the same type as equal
48     (except for the user defined exceptions) to avoid declaring duplicate
49     handlers.
50 
51     All user defined conditions have type==SQLSTATE
52     with the same SQL state and error code.
53     It's OK to have multiple user defined conditions:
54     DECLARE
55       a EXCEPTION;
56       b EXCEPTION;
57     BEGIN
58       RAISE a;
59     EXCEPTION
60       WHEN a THEN RETURN 'a';
61       WHEN b THEN RETURN 'b';
62     END;
63   */
64   if (type != cv->type || m_is_user_defined || cv->m_is_user_defined)
65     return false;
66 
67   switch (type)
68   {
69   case sp_condition_value::ERROR_CODE:
70     return (get_sql_errno() == cv->get_sql_errno());
71 
72   case sp_condition_value::SQLSTATE:
73     return Sql_state::eq(cv);
74 
75   default:
76     return true;
77   }
78 }
79 
80 
81 void sp_pcontext::init(uint var_offset,
82                        uint cursor_offset,
83                        int num_case_expressions)
84 {
85   m_var_offset= var_offset;
86   m_cursor_offset= cursor_offset;
87   m_num_case_exprs= num_case_expressions;
88 
89   m_labels.empty();
90   m_goto_labels.empty();
91 }
92 
93 
94 sp_pcontext::sp_pcontext()
95   : Sql_alloc(),
96   m_max_var_index(0), m_max_cursor_index(0),
97   m_parent(NULL), m_pboundary(0),
98   m_scope(REGULAR_SCOPE)
99 {
100   init(0, 0, 0);
101 }
102 
103 
104 sp_pcontext::sp_pcontext(sp_pcontext *prev, sp_pcontext::enum_scope scope)
105   : Sql_alloc(),
106   m_max_var_index(0), m_max_cursor_index(0),
107   m_parent(prev), m_pboundary(0),
108   m_scope(scope)
109 {
110   init(prev->m_var_offset + prev->m_max_var_index,
111        prev->current_cursor_count(),
112        prev->get_num_case_exprs());
113 }
114 
115 
116 sp_pcontext::~sp_pcontext()
117 {
118   for (size_t i= 0; i < m_children.elements(); ++i)
119     delete m_children.at(i);
120 }
121 
122 
123 sp_pcontext *sp_pcontext::push_context(THD *thd, sp_pcontext::enum_scope scope)
124 {
125   sp_pcontext *child= new (thd->mem_root) sp_pcontext(this, scope);
126 
127   if (child)
128     m_children.append(child);
129   return child;
130 }
131 
132 
133 bool cmp_labels(sp_label *a, sp_label *b)
134 {
135   return (lex_string_cmp(system_charset_info, &a->name, &b->name) == 0 &&
136           a->type == b->type);
137 }
138 
139 sp_pcontext *sp_pcontext::pop_context()
140 {
141   m_parent->m_max_var_index+= m_max_var_index;
142 
143   uint submax= max_cursor_index();
144   if (submax > m_parent->m_max_cursor_index)
145     m_parent->m_max_cursor_index= submax;
146 
147   if (m_num_case_exprs > m_parent->m_num_case_exprs)
148     m_parent->m_num_case_exprs= m_num_case_exprs;
149 
150   /*
151   ** Push unresolved goto label to parent context
152   */
153   sp_label *label;
154   List_iterator_fast<sp_label> li(m_goto_labels);
155   while ((label= li++))
156   {
157     if (label->ip == 0)
158     {
159       m_parent->m_goto_labels.add_unique(label, &cmp_labels);
160     }
161   }
162   return m_parent;
163 }
164 
165 
166 uint sp_pcontext::diff_handlers(const sp_pcontext *ctx, bool exclusive) const
167 {
168   uint n= 0;
169   const sp_pcontext *pctx= this;
170   const sp_pcontext *last_ctx= NULL;
171 
172   while (pctx && pctx != ctx)
173   {
174     n+= (uint)pctx->m_handlers.elements();
175     last_ctx= pctx;
176     pctx= pctx->parent_context();
177   }
178   if (pctx)
179     return (exclusive && last_ctx ? n -(uint) last_ctx->m_handlers.elements() : n);
180   return 0;			// Didn't find ctx
181 }
182 
183 
184 uint sp_pcontext::diff_cursors(const sp_pcontext *ctx, bool exclusive) const
185 {
186   uint n= 0;
187   const sp_pcontext *pctx= this;
188   const sp_pcontext *last_ctx= NULL;
189 
190   while (pctx && pctx != ctx)
191   {
192     n+= (uint)pctx->m_cursors.elements();
193     last_ctx= pctx;
194     pctx= pctx->parent_context();
195   }
196   if (pctx)
197     return  (exclusive && last_ctx ? (uint)(n - last_ctx->m_cursors.elements()) : n);
198   return 0;			// Didn't find ctx
199 }
200 
201 
202 sp_variable *sp_pcontext::find_variable(const LEX_CSTRING *name,
203                                         bool current_scope_only) const
204 {
205   size_t i= m_vars.elements() - m_pboundary;
206 
207   while (i--)
208   {
209     sp_variable *p= m_vars.at(i);
210 
211     if (my_strnncoll(system_charset_info,
212 		     (const uchar *)name->str, name->length,
213 		     (const uchar *)p->name.str, p->name.length) == 0)
214     {
215       return p;
216     }
217   }
218 
219   return (!current_scope_only && m_parent) ?
220     m_parent->find_variable(name, false) :
221     NULL;
222 }
223 
224 
225 /*
226   Find a variable by its run-time offset.
227   If the variable with a desired run-time offset is not found in this
228   context frame, it's recursively searched on parent context frames.
229 
230   Note, context frames can have holes:
231     CREATE PROCEDURE p1() AS
232       x0 INT:=100;
233       CURSOR cur(p0 INT, p1 INT) IS SELECT p0, p1;
234       x1 INT:=101;
235     BEGIN
236       ...
237     END;
238   The variables (x0 and x1) and the cursor parameters (p0 and p1)
239   reside in separate parse context frames.
240 
241   The variables reside on the top level parse context frame:
242   - x0 has frame offset 0 and run-time offset 0
243   - x1 has frame offset 1 and run-time offset 3
244 
245   The cursor parameters reside on the second level parse context frame:
246   - p0 has frame offset 0 and run-time offset 1
247   - p1 has frame offset 1 and run-time offset 2
248 
249   Run-time offsets on a frame can have holes, but offsets monotonocally grow,
250   so run-time offsets of all variables are not greater than the run-time offset
251   of the very last variable in this frame.
252 */
253 sp_variable *sp_pcontext::find_variable(uint offset) const
254 {
255   if (m_var_offset <= offset &&
256       m_vars.elements() &&
257       offset <= get_last_context_variable()->offset)
258   {
259     for (uint i= 0; i < m_vars.elements(); i++)
260     {
261       if (m_vars.at(i)->offset == offset)
262         return m_vars.at(i); // This frame
263     }
264   }
265 
266   return m_parent ?
267          m_parent->find_variable(offset) :    // Some previous frame
268          NULL;                                // Index out of bounds
269 }
270 
271 
272 sp_variable *sp_pcontext::add_variable(THD *thd, const LEX_CSTRING *name)
273 {
274   sp_variable *p=
275     new (thd->mem_root) sp_variable(name, m_var_offset + m_max_var_index);
276 
277   if (!p)
278     return NULL;
279 
280   ++m_max_var_index;
281 
282   return m_vars.append(p) ? NULL : p;
283 }
284 
285 sp_label *sp_pcontext::push_label(THD *thd, const LEX_CSTRING *name, uint ip,
286                                   sp_label::enum_type type,
287                                   List<sp_label> *list)
288 {
289   sp_label *label=
290     new (thd->mem_root) sp_label(name, ip, type, this);
291 
292   if (!label)
293     return NULL;
294 
295   list->push_front(label, thd->mem_root);
296 
297   return label;
298 }
299 
300 sp_label *sp_pcontext::find_goto_label(const LEX_CSTRING *name, bool recusive)
301 {
302   List_iterator_fast<sp_label> li(m_goto_labels);
303   sp_label *lab;
304 
305   while ((lab= li++))
306   {
307     if (lex_string_cmp(system_charset_info, name, &lab->name) == 0)
308       return lab;
309   }
310 
311   if (!recusive)
312     return NULL;
313 
314   /*
315     Note about exception handlers.
316     See SQL:2003 SQL/PSM (ISO/IEC 9075-4:2003),
317     section 13.1 <compound statement>,
318     syntax rule 4.
319     In short, a DECLARE HANDLER block can not refer
320     to labels from the parent context, as they are out of scope.
321   */
322   if (m_scope == HANDLER_SCOPE && m_parent)
323   {
324     if (m_parent->m_parent)
325     {
326       // Skip the parent context
327       return m_parent->m_parent->find_goto_label(name);
328     }
329   }
330 
331   return m_parent && (m_scope == REGULAR_SCOPE) ?
332          m_parent->find_goto_label(name) :
333          NULL;
334 }
335 
336 
337 sp_label *sp_pcontext::find_label(const LEX_CSTRING *name)
338 {
339   List_iterator_fast<sp_label> li(m_labels);
340   sp_label *lab;
341 
342   while ((lab= li++))
343   {
344     if (lex_string_cmp(system_charset_info, name, &lab->name) == 0)
345       return lab;
346   }
347 
348   /*
349     Note about exception handlers.
350     See SQL:2003 SQL/PSM (ISO/IEC 9075-4:2003),
351     section 13.1 <compound statement>,
352     syntax rule 4.
353     In short, a DECLARE HANDLER block can not refer
354     to labels from the parent context, as they are out of scope.
355   */
356   return (m_parent && (m_scope == REGULAR_SCOPE)) ?
357          m_parent->find_label(name) :
358          NULL;
359 }
360 
361 
362 sp_label *sp_pcontext::find_label_current_loop_start()
363 {
364   List_iterator_fast<sp_label> li(m_labels);
365   sp_label *lab;
366 
367   while ((lab= li++))
368   {
369     if (lab->type == sp_label::ITERATION)
370       return lab;
371   }
372   // See a comment in sp_pcontext::find_label()
373   return (m_parent && (m_scope == REGULAR_SCOPE)) ?
374          m_parent->find_label_current_loop_start() :
375          NULL;
376 }
377 
378 
379 bool sp_pcontext::add_condition(THD *thd,
380                                 const LEX_CSTRING *name,
381                                 sp_condition_value *value)
382 {
383   sp_condition *p= new (thd->mem_root) sp_condition(name, value);
384 
385   if (p == NULL)
386     return true;
387 
388   return m_conditions.append(p);
389 }
390 
391 
392 sp_condition_value *sp_pcontext::find_condition(const LEX_CSTRING *name,
393                                                 bool current_scope_only) const
394 {
395   size_t i= m_conditions.elements();
396 
397   while (i--)
398   {
399     sp_condition *p= m_conditions.at(i);
400 
401     if (p->eq_name(name))
402     {
403       return p->value;
404     }
405   }
406 
407   return (!current_scope_only && m_parent) ?
408     m_parent->find_condition(name, false) :
409     NULL;
410 }
411 
412 sp_condition_value *
413 sp_pcontext::find_declared_or_predefined_condition(THD *thd,
414                                                    const LEX_CSTRING *name)
415                                                    const
416 {
417   sp_condition_value *p= find_condition(name, false);
418   if (p)
419     return p;
420   if (thd->variables.sql_mode & MODE_ORACLE)
421     return find_predefined_condition(name);
422   return NULL;
423 }
424 
425 
426 static sp_condition_value
427   // Warnings
428   cond_no_data_found(ER_SP_FETCH_NO_DATA, "01000"),
429   // Errors
430   cond_invalid_cursor(ER_SP_CURSOR_NOT_OPEN, "24000"),
431   cond_dup_val_on_index(ER_DUP_ENTRY, "23000"),
432   cond_dup_val_on_index2(ER_DUP_ENTRY_WITH_KEY_NAME, "23000"),
433   cond_too_many_rows(ER_TOO_MANY_ROWS, "42000");
434 
435 
436 static sp_condition sp_predefined_conditions[]=
437 {
438   // Warnings
439   sp_condition(STRING_WITH_LEN("NO_DATA_FOUND"), &cond_no_data_found),
440   // Errors
441   sp_condition(STRING_WITH_LEN("INVALID_CURSOR"), &cond_invalid_cursor),
442   sp_condition(STRING_WITH_LEN("DUP_VAL_ON_INDEX"), &cond_dup_val_on_index),
443   sp_condition(STRING_WITH_LEN("DUP_VAL_ON_INDEX"), &cond_dup_val_on_index2),
444   sp_condition(STRING_WITH_LEN("TOO_MANY_ROWS"), &cond_too_many_rows)
445 };
446 
447 
448 sp_condition_value *
449 sp_pcontext::find_predefined_condition(const LEX_CSTRING *name) const
450 {
451   for (uint i= 0; i < array_elements(sp_predefined_conditions) ; i++)
452   {
453     if (sp_predefined_conditions[i].eq_name(name))
454       return sp_predefined_conditions[i].value;
455   }
456   return NULL;
457 }
458 
459 
460 sp_handler *sp_pcontext::add_handler(THD *thd,
461                                      sp_handler::enum_type type)
462 {
463   sp_handler *h= new (thd->mem_root) sp_handler(type);
464 
465   if (!h)
466     return NULL;
467 
468   return m_handlers.append(h) ? NULL : h;
469 }
470 
471 
472 bool sp_pcontext::check_duplicate_handler(
473   const sp_condition_value *cond_value) const
474 {
475   for (size_t i= 0; i < m_handlers.elements(); ++i)
476   {
477     sp_handler *h= m_handlers.at(i);
478 
479     List_iterator_fast<sp_condition_value> li(h->condition_values);
480     sp_condition_value *cv;
481 
482     while ((cv= li++))
483     {
484       if (cond_value->equals(cv))
485         return true;
486     }
487   }
488 
489   return false;
490 }
491 
492 
493 bool sp_condition_value::matches(const Sql_condition_identity &value,
494                                  const sp_condition_value *found_cv) const
495 {
496   bool user_value_matched= !value.get_user_condition_value() ||
497                            this == value.get_user_condition_value();
498 
499   switch (type)
500   {
501   case sp_condition_value::ERROR_CODE:
502     return user_value_matched &&
503            value.get_sql_errno() == get_sql_errno() &&
504            (!found_cv || found_cv->type > sp_condition_value::ERROR_CODE);
505 
506   case sp_condition_value::SQLSTATE:
507     return user_value_matched &&
508            Sql_state::eq(&value) &&
509            (!found_cv || found_cv->type > sp_condition_value::SQLSTATE);
510 
511   case sp_condition_value::WARNING:
512     return user_value_matched &&
513            (value.Sql_state::is_warning() ||
514             value.get_level() == Sql_condition::WARN_LEVEL_WARN) &&
515            !found_cv;
516 
517   case sp_condition_value::NOT_FOUND:
518     return user_value_matched &&
519            value.Sql_state::is_not_found() &&
520            !found_cv;
521 
522   case sp_condition_value::EXCEPTION:
523     /*
524       In sql_mode=ORACLE this construct should catch both errors and warnings:
525         EXCEPTION
526           WHEN OTHERS THEN ...;
527       E.g. NO_DATA_FOUND is more like a warning than an error,
528       and it should be caught.
529 
530       We don't check user_value_matched here.
531       "WHEN OTHERS" catches all user defined exception.
532     */
533     return (((current_thd->variables.sql_mode & MODE_ORACLE) ||
534            (value.Sql_state::is_exception() &&
535             value.get_level() == Sql_condition::WARN_LEVEL_ERROR)) &&
536            !found_cv);
537   }
538   return false;
539 }
540 
541 
542 sp_handler*
543 sp_pcontext::find_handler(const Sql_condition_identity &value) const
544 {
545   sp_handler *found_handler= NULL;
546   sp_condition_value *found_cv= NULL;
547 
548   for (size_t i= 0; i < m_handlers.elements(); ++i)
549   {
550     sp_handler *h= m_handlers.at(i);
551 
552     List_iterator_fast<sp_condition_value> li(h->condition_values);
553     sp_condition_value *cv;
554 
555     while ((cv= li++))
556     {
557       if (cv->matches(value, found_cv))
558       {
559         found_cv= cv;
560         found_handler= h;
561       }
562     }
563   }
564 
565   if (found_handler)
566     return found_handler;
567 
568 
569   // There is no appropriate handler in this parsing context. We need to look up
570   // in parent contexts. There might be two cases here:
571   //
572   // 1. The current context has REGULAR_SCOPE. That means, it's a simple
573   // BEGIN..END block:
574   //     ...
575   //     BEGIN
576   //       ... # We're here.
577   //     END
578   //     ...
579   // In this case we simply call find_handler() on parent's context recursively.
580   //
581   // 2. The current context has HANDLER_SCOPE. That means, we're inside an
582   // SQL-handler block:
583   //   ...
584   //   DECLARE ... HANDLER FOR ...
585   //   BEGIN
586   //     ... # We're here.
587   //   END
588   //   ...
589   // In this case we can not just call parent's find_handler(), because
590   // parent's handler don't catch conditions from this scope. Instead, we should
591   // try to find first parent context (we might have nested handler
592   // declarations), which has REGULAR_SCOPE (i.e. which is regular BEGIN..END
593   // block).
594 
595   const sp_pcontext *p= this;
596 
597   while (p && p->m_scope == HANDLER_SCOPE)
598     p= p->m_parent;
599 
600   if (!p || !p->m_parent)
601     return NULL;
602 
603   return p->m_parent->find_handler(value);
604 }
605 
606 
607 bool sp_pcontext::add_cursor(const LEX_CSTRING *name, sp_pcontext *param_ctx,
608                              sp_lex_cursor *lex)
609 {
610   if (m_cursors.elements() == m_max_cursor_index)
611     ++m_max_cursor_index;
612 
613   return m_cursors.append(sp_pcursor(name, param_ctx, lex));
614 }
615 
616 
617 const sp_pcursor *sp_pcontext::find_cursor(const LEX_CSTRING *name,
618                                            uint *poff,
619                                            bool current_scope_only) const
620 {
621   uint i= (uint)m_cursors.elements();
622 
623   while (i--)
624   {
625     LEX_CSTRING n= m_cursors.at(i);
626 
627     if (my_strnncoll(system_charset_info,
628 		     (const uchar *) name->str, name->length,
629 		     (const uchar *) n.str, n.length) == 0)
630     {
631       *poff= m_cursor_offset + i;
632       return &m_cursors.at(i);
633     }
634   }
635 
636   return (!current_scope_only && m_parent) ?
637     m_parent->find_cursor(name, poff, false) :
638     NULL;
639 }
640 
641 
642 void sp_pcontext::retrieve_field_definitions(
643   List<Spvar_definition> *field_def_lst) const
644 {
645   /* Put local/context fields in the result list. */
646 
647   size_t next_child= 0;
648   for (size_t i= 0; i < m_vars.elements(); ++i)
649   {
650     sp_variable *var_def= m_vars.at(i);
651 
652     /*
653       The context can have holes in run-time offsets,
654       the missing offsets reside on the children contexts in such cases.
655       Example:
656         CREATE PROCEDURE p1() AS
657           x0 INT:=100;        -- context 0, position 0, run-time 0
658           CURSOR cur(
659             p0 INT,           -- context 1, position 0, run-time 1
660             p1 INT            -- context 1, position 1, run-time 2
661           ) IS SELECT p0, p1;
662           x1 INT:=101;        -- context 0, position 1, run-time 3
663         BEGIN
664           ...
665         END;
666       See more comments in sp_pcontext::find_variable().
667       We must retrieve the definitions in the order of their run-time offsets.
668       Check that there are children that should go before the current variable.
669     */
670     for ( ; next_child < m_children.elements(); next_child++)
671     {
672       sp_pcontext *child= m_children.at(next_child);
673       if (!child->context_var_count() ||
674           child->get_context_variable(0)->offset > var_def->offset)
675         break;
676       /*
677         All variables on the embedded context (that fills holes of the parent)
678         should have the run-time offset strictly less than var_def.
679       */
680       DBUG_ASSERT(child->get_context_variable(0)->offset < var_def->offset);
681       DBUG_ASSERT(child->get_last_context_variable()->offset < var_def->offset);
682       child->retrieve_field_definitions(field_def_lst);
683     }
684     field_def_lst->push_back(&var_def->field_def);
685   }
686 
687   /* Put the fields of the remaining enclosed contexts in the result list. */
688 
689   for (size_t i= next_child; i < m_children.elements(); ++i)
690     m_children.at(i)->retrieve_field_definitions(field_def_lst);
691 }
692 
693 
694 const sp_pcursor *sp_pcontext::find_cursor(uint offset) const
695 {
696   if (m_cursor_offset <= offset &&
697       offset < m_cursor_offset + m_cursors.elements())
698   {
699     return &m_cursors.at(offset - m_cursor_offset);   // This frame
700   }
701 
702   return m_parent ?
703          m_parent->find_cursor(offset) :  // Some previous frame
704          NULL;                            // Index out of bounds
705 }
706 
707 
708 bool sp_pcursor::check_param_count_with_error(uint param_count) const
709 {
710   if (param_count != (m_param_context ?
711                       m_param_context->context_var_count() : 0))
712   {
713     my_error(ER_WRONG_PARAMCOUNT_TO_CURSOR, MYF(0), LEX_CSTRING::str);
714     return true;
715   }
716   return false;
717 }
718 
719 
720 const Spvar_definition *
721 sp_variable::find_row_field(const LEX_CSTRING *var_name,
722                             const LEX_CSTRING *field_name,
723                             uint *row_field_offset)
724 {
725   if (!field_def.is_row())
726   {
727     my_printf_error(ER_UNKNOWN_ERROR,
728                     "'%s' is not a row variable", MYF(0), var_name->str);
729     return NULL;
730   }
731   const Spvar_definition *def;
732   if ((def= field_def.find_row_field_by_name(field_name, row_field_offset)))
733     return def;
734   my_error(ER_ROW_VARIABLE_DOES_NOT_HAVE_FIELD, MYF(0),
735            var_name->str, field_name->str);
736   return NULL;
737 }
738