2011-06-30 17:46:53 +02:00
|
|
|
/* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
|
2020-01-26 17:27:13 +01:00
|
|
|
Copyright (c) 2009, 2020, MariaDB Corporation.
|
Simplistic, experimental framework for Stored Procedures (SPs).
Implements creation and dropping of PROCEDUREs, IN, OUT, and INOUT parameters,
single-statement procedures, rudimentary multi-statement (begin-end) prodedures
(when the client can handle it), and local variables.
Missing most of the embedded SQL language, all attributes, FUNCTIONs, error handling,
reparses procedures at each call (no caching), etc, etc.
Certainly buggy too, but procedures can actually be created and called....
sql/Makefile.am:
Added SP files.
sql/item.cc:
Added this*_item() methods for Item_splocal. (SP local variable)
sql/item.h:
Added this*_item() methods for SPs in Item, and the new Item_splocal
class (SP local variable).
sql/lex.h:
Added new symbols for SPs. (Note: SPSET is temporary and will go away later.)
sql/sql_class.cc:
Initialize SP runtime context in THD.
sql/sql_class.h:
Add SP runtime context to THD.
sql/sql_lex.cc:
Init. buf pointer to beginning of command (needed by SPs).
Also initialize SP head and parse time context.
sql/sql_lex.h:
New SQLCOM_ tags for SPs, and added pointer to beginning of command pointer and
SP head and parse-time context to LEX.
sql/sql_parse.cc:
Added SQLCOM_CREATE_PROCEDURE, _CALL, _ALTER_PROCEDURE and _DROP_PROCEDURE cases.
(Still rudimentary and lacking proper error handling...)
sql/sql_yacc.yy:
Lots and lots of additions for SPs...
(Still even more missing, and no error messages...)
2002-12-08 19:59:22 +01:00
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
2006-12-23 20:17:15 +01:00
|
|
|
the Free Software Foundation; version 2 of the License.
|
Simplistic, experimental framework for Stored Procedures (SPs).
Implements creation and dropping of PROCEDUREs, IN, OUT, and INOUT parameters,
single-statement procedures, rudimentary multi-statement (begin-end) prodedures
(when the client can handle it), and local variables.
Missing most of the embedded SQL language, all attributes, FUNCTIONs, error handling,
reparses procedures at each call (no caching), etc, etc.
Certainly buggy too, but procedures can actually be created and called....
sql/Makefile.am:
Added SP files.
sql/item.cc:
Added this*_item() methods for Item_splocal. (SP local variable)
sql/item.h:
Added this*_item() methods for SPs in Item, and the new Item_splocal
class (SP local variable).
sql/lex.h:
Added new symbols for SPs. (Note: SPSET is temporary and will go away later.)
sql/sql_class.cc:
Initialize SP runtime context in THD.
sql/sql_class.h:
Add SP runtime context to THD.
sql/sql_lex.cc:
Init. buf pointer to beginning of command (needed by SPs).
Also initialize SP head and parse time context.
sql/sql_lex.h:
New SQLCOM_ tags for SPs, and added pointer to beginning of command pointer and
SP head and parse-time context to LEX.
sql/sql_parse.cc:
Added SQLCOM_CREATE_PROCEDURE, _CALL, _ALTER_PROCEDURE and _DROP_PROCEDURE cases.
(Still rudimentary and lacking proper error handling...)
sql/sql_yacc.yy:
Lots and lots of additions for SPs...
(Still even more missing, and no error messages...)
2002-12-08 19:59:22 +01:00
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
2019-05-11 20:29:06 +02:00
|
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
|
Simplistic, experimental framework for Stored Procedures (SPs).
Implements creation and dropping of PROCEDUREs, IN, OUT, and INOUT parameters,
single-statement procedures, rudimentary multi-statement (begin-end) prodedures
(when the client can handle it), and local variables.
Missing most of the embedded SQL language, all attributes, FUNCTIONs, error handling,
reparses procedures at each call (no caching), etc, etc.
Certainly buggy too, but procedures can actually be created and called....
sql/Makefile.am:
Added SP files.
sql/item.cc:
Added this*_item() methods for Item_splocal. (SP local variable)
sql/item.h:
Added this*_item() methods for SPs in Item, and the new Item_splocal
class (SP local variable).
sql/lex.h:
Added new symbols for SPs. (Note: SPSET is temporary and will go away later.)
sql/sql_class.cc:
Initialize SP runtime context in THD.
sql/sql_class.h:
Add SP runtime context to THD.
sql/sql_lex.cc:
Init. buf pointer to beginning of command (needed by SPs).
Also initialize SP head and parse time context.
sql/sql_lex.h:
New SQLCOM_ tags for SPs, and added pointer to beginning of command pointer and
SP head and parse-time context to LEX.
sql/sql_parse.cc:
Added SQLCOM_CREATE_PROCEDURE, _CALL, _ALTER_PROCEDURE and _DROP_PROCEDURE cases.
(Still rudimentary and lacking proper error handling...)
sql/sql_yacc.yy:
Lots and lots of additions for SPs...
(Still even more missing, and no error messages...)
2002-12-08 19:59:22 +01:00
|
|
|
|
2017-06-18 05:42:16 +02:00
|
|
|
#include "mariadb.h"
|
2010-03-31 16:05:33 +02:00
|
|
|
#include "sql_priv.h"
|
|
|
|
#include "unireg.h"
|
2005-05-27 12:03:37 +02:00
|
|
|
#ifdef USE_PRAGMA_IMPLEMENTATION
|
Simplistic, experimental framework for Stored Procedures (SPs).
Implements creation and dropping of PROCEDUREs, IN, OUT, and INOUT parameters,
single-statement procedures, rudimentary multi-statement (begin-end) prodedures
(when the client can handle it), and local variables.
Missing most of the embedded SQL language, all attributes, FUNCTIONs, error handling,
reparses procedures at each call (no caching), etc, etc.
Certainly buggy too, but procedures can actually be created and called....
sql/Makefile.am:
Added SP files.
sql/item.cc:
Added this*_item() methods for Item_splocal. (SP local variable)
sql/item.h:
Added this*_item() methods for SPs in Item, and the new Item_splocal
class (SP local variable).
sql/lex.h:
Added new symbols for SPs. (Note: SPSET is temporary and will go away later.)
sql/sql_class.cc:
Initialize SP runtime context in THD.
sql/sql_class.h:
Add SP runtime context to THD.
sql/sql_lex.cc:
Init. buf pointer to beginning of command (needed by SPs).
Also initialize SP head and parse time context.
sql/sql_lex.h:
New SQLCOM_ tags for SPs, and added pointer to beginning of command pointer and
SP head and parse-time context to LEX.
sql/sql_parse.cc:
Added SQLCOM_CREATE_PROCEDURE, _CALL, _ALTER_PROCEDURE and _DROP_PROCEDURE cases.
(Still rudimentary and lacking proper error handling...)
sql/sql_yacc.yy:
Lots and lots of additions for SPs...
(Still even more missing, and no error messages...)
2002-12-08 19:59:22 +01:00
|
|
|
#pragma implementation
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "sp_pcontext.h"
|
2002-12-11 14:24:29 +01:00
|
|
|
#include "sp_head.h"
|
Simplistic, experimental framework for Stored Procedures (SPs).
Implements creation and dropping of PROCEDUREs, IN, OUT, and INOUT parameters,
single-statement procedures, rudimentary multi-statement (begin-end) prodedures
(when the client can handle it), and local variables.
Missing most of the embedded SQL language, all attributes, FUNCTIONs, error handling,
reparses procedures at each call (no caching), etc, etc.
Certainly buggy too, but procedures can actually be created and called....
sql/Makefile.am:
Added SP files.
sql/item.cc:
Added this*_item() methods for Item_splocal. (SP local variable)
sql/item.h:
Added this*_item() methods for SPs in Item, and the new Item_splocal
class (SP local variable).
sql/lex.h:
Added new symbols for SPs. (Note: SPSET is temporary and will go away later.)
sql/sql_class.cc:
Initialize SP runtime context in THD.
sql/sql_class.h:
Add SP runtime context to THD.
sql/sql_lex.cc:
Init. buf pointer to beginning of command (needed by SPs).
Also initialize SP head and parse time context.
sql/sql_lex.h:
New SQLCOM_ tags for SPs, and added pointer to beginning of command pointer and
SP head and parse-time context to LEX.
sql/sql_parse.cc:
Added SQLCOM_CREATE_PROCEDURE, _CALL, _ALTER_PROCEDURE and _DROP_PROCEDURE cases.
(Still rudimentary and lacking proper error handling...)
sql/sql_yacc.yy:
Lots and lots of additions for SPs...
(Still even more missing, and no error messages...)
2002-12-08 19:59:22 +01:00
|
|
|
|
2013-06-19 13:32:14 +02:00
|
|
|
bool sp_condition_value::equals(const sp_condition_value *cv) const
|
2005-02-28 18:07:06 +01:00
|
|
|
{
|
2013-06-19 13:32:14 +02:00
|
|
|
DBUG_ASSERT(cv);
|
2005-02-28 18:07:06 +01:00
|
|
|
|
2016-10-14 14:52:33 +02:00
|
|
|
/*
|
|
|
|
The following test disallows duplicate handlers,
|
|
|
|
including user defined exceptions with the same WHEN clause:
|
|
|
|
DECLARE
|
|
|
|
a EXCEPTION;
|
|
|
|
b EXCEPTION;
|
|
|
|
BEGIN
|
|
|
|
RAUSE a;
|
|
|
|
EXCEPTION
|
|
|
|
WHEN a THEN RETURN 'a0';
|
|
|
|
WHEN a THEN RETURN 'a1';
|
|
|
|
END
|
|
|
|
*/
|
2013-06-19 13:32:14 +02:00
|
|
|
if (this == cv)
|
|
|
|
return true;
|
|
|
|
|
2016-10-14 14:52:33 +02:00
|
|
|
/*
|
|
|
|
The test below considers two conditions of the same type as equal
|
|
|
|
(except for the user defined exceptions) to avoid declaring duplicate
|
|
|
|
handlers.
|
|
|
|
|
|
|
|
All user defined conditions have type==SQLSTATE
|
|
|
|
with the same SQL state and error code.
|
|
|
|
It's OK to have multiple user defined conditions:
|
|
|
|
DECLARE
|
|
|
|
a EXCEPTION;
|
|
|
|
b EXCEPTION;
|
|
|
|
BEGIN
|
|
|
|
RAISE a;
|
|
|
|
EXCEPTION
|
|
|
|
WHEN a THEN RETURN 'a';
|
|
|
|
WHEN b THEN RETURN 'b';
|
|
|
|
END;
|
|
|
|
*/
|
|
|
|
if (type != cv->type || m_is_user_defined || cv->m_is_user_defined)
|
2013-06-19 13:32:14 +02:00
|
|
|
return false;
|
|
|
|
|
|
|
|
switch (type)
|
2005-02-28 18:07:06 +01:00
|
|
|
{
|
2013-06-19 13:32:14 +02:00
|
|
|
case sp_condition_value::ERROR_CODE:
|
2016-10-12 16:16:38 +02:00
|
|
|
return (get_sql_errno() == cv->get_sql_errno());
|
2013-06-19 13:32:14 +02:00
|
|
|
|
|
|
|
case sp_condition_value::SQLSTATE:
|
2016-10-12 16:16:38 +02:00
|
|
|
return Sql_state::eq(cv);
|
2005-02-28 18:07:06 +01:00
|
|
|
|
2013-06-19 13:32:14 +02:00
|
|
|
default:
|
|
|
|
return true;
|
2005-02-28 18:07:06 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-19 13:32:14 +02:00
|
|
|
|
|
|
|
void sp_pcontext::init(uint var_offset,
|
|
|
|
uint cursor_offset,
|
|
|
|
int num_case_expressions)
|
|
|
|
{
|
|
|
|
m_var_offset= var_offset;
|
|
|
|
m_cursor_offset= cursor_offset;
|
|
|
|
m_num_case_exprs= num_case_expressions;
|
|
|
|
|
|
|
|
m_labels.empty();
|
2017-02-14 14:43:11 +01:00
|
|
|
m_goto_labels.empty();
|
2013-06-19 13:32:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
Bug#26503 (Illegal SQL exception handler code causes the server to crash)
Before this fix, the parser would accept illegal code in SQL exceptions
handlers, that later causes the runtime to crash when executing the code,
due to memory violations in the exception handler stack.
The root cause of the problem is instructions within an exception handler
that jumps to code located outside of the handler. This is illegal according
to the SQL 2003 standard, since labels located outside the handler are not
supposed to be visible (they are "out of scope"), so any instruction that
jumps to these labels, like ITERATE or LEAVE, should not parse.
The section of the standard that is relevant for this is :
SQL:2003 SQL/PSM (ISO/IEC 9075-4:2003)
section 13.1 <compound statement>,
syntax rule 4
<quote>
The scope of the <beginning label> is CS excluding every <SQL schema
statement> contained in CS and excluding every
<local handler declaration list> contained in CS. <beginning label> shall
not be equivalent to any other <beginning label>s within that scope.
</quote>
With this fix, the C++ class sp_pcontext, which represent the "parsing
context" tree (a.k.a symbol table) of a stored procedure, has been changed
as follows:
- constructors have been cleaned up, so that only building a root node for
the tree is public; building nodes inside a tree is not public.
- a new member, m_label_scope, indicates if a given syntactic context
belongs to a DECLARE HANDLER block,
- label resolution, in the method find_label(), has been changed to
implement the restriction of scope regarding labels used in a compound
statement.
The actions in the parser, when parsing the body of a SQL exception handler,
have been changed as follows:
- the implementation of an exception handler (DECLARE HANDLER) now creates
explicitly a new sp_pcontext, to isolate the code inside the handler from
the containing compound statement context.
- registering exception handlers as a result occurs in the parent context,
see the rule sp_hcond_element
- the code in sp_hcond_list has been cleaned up, to avoid code duplication
In addition, the flags IN_SIMPLE_CASE and IN_HANDLER, declared in sp_head.h
have been removed, since they are unused and broken by design (as seen with
Bug 19194 (Right recursion in parser for CASE causes excessive stack usage,
limitation), representing a stack in a single flag is not possible.
Tests in sp-error have been added to show that illegal constructs are now
rejected.
Tests in sp have been added for code coverage, to show that ITERATE or LEAVE
statements are legal when jumping to a label in scope, inside the body of
an exception handler.
mysql-test/r/sp-error.result:
SQL Exception handlers define a parsing context for label resolution.
mysql-test/r/sp.result:
SQL Exception handlers define a parsing context for label resolution.
mysql-test/t/sp-error.test:
SQL Exception handlers define a parsing context for label resolution.
mysql-test/t/sp.test:
SQL Exception handlers define a parsing context for label resolution.
sql/sp_head.cc:
Minor cleanup
sql/sp_head.h:
Minor cleanup
sql/sp_pcontext.cc:
SQL Exception handlers define a parsing context for label resolution.
sql/sp_pcontext.h:
SQL Exception handlers define a parsing context for label resolution.
sql/sql_yacc.yy:
SQL Exception handlers define a parsing context for label resolution.
2007-03-14 19:02:32 +01:00
|
|
|
sp_pcontext::sp_pcontext()
|
|
|
|
: Sql_alloc(),
|
2013-06-19 13:32:14 +02:00
|
|
|
m_max_var_index(0), m_max_cursor_index(0),
|
|
|
|
m_parent(NULL), m_pboundary(0),
|
2020-01-29 13:50:26 +01:00
|
|
|
m_vars(PSI_INSTRUMENT_MEM), m_case_expr_ids(PSI_INSTRUMENT_MEM),
|
|
|
|
m_conditions(PSI_INSTRUMENT_MEM), m_cursors(PSI_INSTRUMENT_MEM),
|
|
|
|
m_handlers(PSI_INSTRUMENT_MEM), m_children(PSI_INSTRUMENT_MEM),
|
2013-06-19 13:32:14 +02:00
|
|
|
m_scope(REGULAR_SCOPE)
|
Simplistic, experimental framework for Stored Procedures (SPs).
Implements creation and dropping of PROCEDUREs, IN, OUT, and INOUT parameters,
single-statement procedures, rudimentary multi-statement (begin-end) prodedures
(when the client can handle it), and local variables.
Missing most of the embedded SQL language, all attributes, FUNCTIONs, error handling,
reparses procedures at each call (no caching), etc, etc.
Certainly buggy too, but procedures can actually be created and called....
sql/Makefile.am:
Added SP files.
sql/item.cc:
Added this*_item() methods for Item_splocal. (SP local variable)
sql/item.h:
Added this*_item() methods for SPs in Item, and the new Item_splocal
class (SP local variable).
sql/lex.h:
Added new symbols for SPs. (Note: SPSET is temporary and will go away later.)
sql/sql_class.cc:
Initialize SP runtime context in THD.
sql/sql_class.h:
Add SP runtime context to THD.
sql/sql_lex.cc:
Init. buf pointer to beginning of command (needed by SPs).
Also initialize SP head and parse time context.
sql/sql_lex.h:
New SQLCOM_ tags for SPs, and added pointer to beginning of command pointer and
SP head and parse-time context to LEX.
sql/sql_parse.cc:
Added SQLCOM_CREATE_PROCEDURE, _CALL, _ALTER_PROCEDURE and _DROP_PROCEDURE cases.
(Still rudimentary and lacking proper error handling...)
sql/sql_yacc.yy:
Lots and lots of additions for SPs...
(Still even more missing, and no error messages...)
2002-12-08 19:59:22 +01:00
|
|
|
{
|
2013-06-19 13:32:14 +02:00
|
|
|
init(0, 0, 0);
|
Bug#26503 (Illegal SQL exception handler code causes the server to crash)
Before this fix, the parser would accept illegal code in SQL exceptions
handlers, that later causes the runtime to crash when executing the code,
due to memory violations in the exception handler stack.
The root cause of the problem is instructions within an exception handler
that jumps to code located outside of the handler. This is illegal according
to the SQL 2003 standard, since labels located outside the handler are not
supposed to be visible (they are "out of scope"), so any instruction that
jumps to these labels, like ITERATE or LEAVE, should not parse.
The section of the standard that is relevant for this is :
SQL:2003 SQL/PSM (ISO/IEC 9075-4:2003)
section 13.1 <compound statement>,
syntax rule 4
<quote>
The scope of the <beginning label> is CS excluding every <SQL schema
statement> contained in CS and excluding every
<local handler declaration list> contained in CS. <beginning label> shall
not be equivalent to any other <beginning label>s within that scope.
</quote>
With this fix, the C++ class sp_pcontext, which represent the "parsing
context" tree (a.k.a symbol table) of a stored procedure, has been changed
as follows:
- constructors have been cleaned up, so that only building a root node for
the tree is public; building nodes inside a tree is not public.
- a new member, m_label_scope, indicates if a given syntactic context
belongs to a DECLARE HANDLER block,
- label resolution, in the method find_label(), has been changed to
implement the restriction of scope regarding labels used in a compound
statement.
The actions in the parser, when parsing the body of a SQL exception handler,
have been changed as follows:
- the implementation of an exception handler (DECLARE HANDLER) now creates
explicitly a new sp_pcontext, to isolate the code inside the handler from
the containing compound statement context.
- registering exception handlers as a result occurs in the parent context,
see the rule sp_hcond_element
- the code in sp_hcond_list has been cleaned up, to avoid code duplication
In addition, the flags IN_SIMPLE_CASE and IN_HANDLER, declared in sp_head.h
have been removed, since they are unused and broken by design (as seen with
Bug 19194 (Right recursion in parser for CASE causes excessive stack usage,
limitation), representing a stack in a single flag is not possible.
Tests in sp-error have been added to show that illegal constructs are now
rejected.
Tests in sp have been added for code coverage, to show that ITERATE or LEAVE
statements are legal when jumping to a label in scope, inside the body of
an exception handler.
mysql-test/r/sp-error.result:
SQL Exception handlers define a parsing context for label resolution.
mysql-test/r/sp.result:
SQL Exception handlers define a parsing context for label resolution.
mysql-test/t/sp-error.test:
SQL Exception handlers define a parsing context for label resolution.
mysql-test/t/sp.test:
SQL Exception handlers define a parsing context for label resolution.
sql/sp_head.cc:
Minor cleanup
sql/sp_head.h:
Minor cleanup
sql/sp_pcontext.cc:
SQL Exception handlers define a parsing context for label resolution.
sql/sp_pcontext.h:
SQL Exception handlers define a parsing context for label resolution.
sql/sql_yacc.yy:
SQL Exception handlers define a parsing context for label resolution.
2007-03-14 19:02:32 +01:00
|
|
|
}
|
|
|
|
|
2013-06-19 13:32:14 +02:00
|
|
|
|
|
|
|
sp_pcontext::sp_pcontext(sp_pcontext *prev, sp_pcontext::enum_scope scope)
|
Bug#26503 (Illegal SQL exception handler code causes the server to crash)
Before this fix, the parser would accept illegal code in SQL exceptions
handlers, that later causes the runtime to crash when executing the code,
due to memory violations in the exception handler stack.
The root cause of the problem is instructions within an exception handler
that jumps to code located outside of the handler. This is illegal according
to the SQL 2003 standard, since labels located outside the handler are not
supposed to be visible (they are "out of scope"), so any instruction that
jumps to these labels, like ITERATE or LEAVE, should not parse.
The section of the standard that is relevant for this is :
SQL:2003 SQL/PSM (ISO/IEC 9075-4:2003)
section 13.1 <compound statement>,
syntax rule 4
<quote>
The scope of the <beginning label> is CS excluding every <SQL schema
statement> contained in CS and excluding every
<local handler declaration list> contained in CS. <beginning label> shall
not be equivalent to any other <beginning label>s within that scope.
</quote>
With this fix, the C++ class sp_pcontext, which represent the "parsing
context" tree (a.k.a symbol table) of a stored procedure, has been changed
as follows:
- constructors have been cleaned up, so that only building a root node for
the tree is public; building nodes inside a tree is not public.
- a new member, m_label_scope, indicates if a given syntactic context
belongs to a DECLARE HANDLER block,
- label resolution, in the method find_label(), has been changed to
implement the restriction of scope regarding labels used in a compound
statement.
The actions in the parser, when parsing the body of a SQL exception handler,
have been changed as follows:
- the implementation of an exception handler (DECLARE HANDLER) now creates
explicitly a new sp_pcontext, to isolate the code inside the handler from
the containing compound statement context.
- registering exception handlers as a result occurs in the parent context,
see the rule sp_hcond_element
- the code in sp_hcond_list has been cleaned up, to avoid code duplication
In addition, the flags IN_SIMPLE_CASE and IN_HANDLER, declared in sp_head.h
have been removed, since they are unused and broken by design (as seen with
Bug 19194 (Right recursion in parser for CASE causes excessive stack usage,
limitation), representing a stack in a single flag is not possible.
Tests in sp-error have been added to show that illegal constructs are now
rejected.
Tests in sp have been added for code coverage, to show that ITERATE or LEAVE
statements are legal when jumping to a label in scope, inside the body of
an exception handler.
mysql-test/r/sp-error.result:
SQL Exception handlers define a parsing context for label resolution.
mysql-test/r/sp.result:
SQL Exception handlers define a parsing context for label resolution.
mysql-test/t/sp-error.test:
SQL Exception handlers define a parsing context for label resolution.
mysql-test/t/sp.test:
SQL Exception handlers define a parsing context for label resolution.
sql/sp_head.cc:
Minor cleanup
sql/sp_head.h:
Minor cleanup
sql/sp_pcontext.cc:
SQL Exception handlers define a parsing context for label resolution.
sql/sp_pcontext.h:
SQL Exception handlers define a parsing context for label resolution.
sql/sql_yacc.yy:
SQL Exception handlers define a parsing context for label resolution.
2007-03-14 19:02:32 +01:00
|
|
|
: Sql_alloc(),
|
2013-06-19 13:32:14 +02:00
|
|
|
m_max_var_index(0), m_max_cursor_index(0),
|
|
|
|
m_parent(prev), m_pboundary(0),
|
2020-01-29 13:50:26 +01:00
|
|
|
m_vars(PSI_INSTRUMENT_MEM), m_case_expr_ids(PSI_INSTRUMENT_MEM),
|
|
|
|
m_conditions(PSI_INSTRUMENT_MEM), m_cursors(PSI_INSTRUMENT_MEM),
|
|
|
|
m_handlers(PSI_INSTRUMENT_MEM), m_children(PSI_INSTRUMENT_MEM),
|
2013-06-19 13:32:14 +02:00
|
|
|
m_scope(scope)
|
Bug#26503 (Illegal SQL exception handler code causes the server to crash)
Before this fix, the parser would accept illegal code in SQL exceptions
handlers, that later causes the runtime to crash when executing the code,
due to memory violations in the exception handler stack.
The root cause of the problem is instructions within an exception handler
that jumps to code located outside of the handler. This is illegal according
to the SQL 2003 standard, since labels located outside the handler are not
supposed to be visible (they are "out of scope"), so any instruction that
jumps to these labels, like ITERATE or LEAVE, should not parse.
The section of the standard that is relevant for this is :
SQL:2003 SQL/PSM (ISO/IEC 9075-4:2003)
section 13.1 <compound statement>,
syntax rule 4
<quote>
The scope of the <beginning label> is CS excluding every <SQL schema
statement> contained in CS and excluding every
<local handler declaration list> contained in CS. <beginning label> shall
not be equivalent to any other <beginning label>s within that scope.
</quote>
With this fix, the C++ class sp_pcontext, which represent the "parsing
context" tree (a.k.a symbol table) of a stored procedure, has been changed
as follows:
- constructors have been cleaned up, so that only building a root node for
the tree is public; building nodes inside a tree is not public.
- a new member, m_label_scope, indicates if a given syntactic context
belongs to a DECLARE HANDLER block,
- label resolution, in the method find_label(), has been changed to
implement the restriction of scope regarding labels used in a compound
statement.
The actions in the parser, when parsing the body of a SQL exception handler,
have been changed as follows:
- the implementation of an exception handler (DECLARE HANDLER) now creates
explicitly a new sp_pcontext, to isolate the code inside the handler from
the containing compound statement context.
- registering exception handlers as a result occurs in the parent context,
see the rule sp_hcond_element
- the code in sp_hcond_list has been cleaned up, to avoid code duplication
In addition, the flags IN_SIMPLE_CASE and IN_HANDLER, declared in sp_head.h
have been removed, since they are unused and broken by design (as seen with
Bug 19194 (Right recursion in parser for CASE causes excessive stack usage,
limitation), representing a stack in a single flag is not possible.
Tests in sp-error have been added to show that illegal constructs are now
rejected.
Tests in sp have been added for code coverage, to show that ITERATE or LEAVE
statements are legal when jumping to a label in scope, inside the body of
an exception handler.
mysql-test/r/sp-error.result:
SQL Exception handlers define a parsing context for label resolution.
mysql-test/r/sp.result:
SQL Exception handlers define a parsing context for label resolution.
mysql-test/t/sp-error.test:
SQL Exception handlers define a parsing context for label resolution.
mysql-test/t/sp.test:
SQL Exception handlers define a parsing context for label resolution.
sql/sp_head.cc:
Minor cleanup
sql/sp_head.h:
Minor cleanup
sql/sp_pcontext.cc:
SQL Exception handlers define a parsing context for label resolution.
sql/sp_pcontext.h:
SQL Exception handlers define a parsing context for label resolution.
sql/sql_yacc.yy:
SQL Exception handlers define a parsing context for label resolution.
2007-03-14 19:02:32 +01:00
|
|
|
{
|
2013-06-19 13:32:14 +02:00
|
|
|
init(prev->m_var_offset + prev->m_max_var_index,
|
|
|
|
prev->current_cursor_count(),
|
|
|
|
prev->get_num_case_exprs());
|
Simplistic, experimental framework for Stored Procedures (SPs).
Implements creation and dropping of PROCEDUREs, IN, OUT, and INOUT parameters,
single-statement procedures, rudimentary multi-statement (begin-end) prodedures
(when the client can handle it), and local variables.
Missing most of the embedded SQL language, all attributes, FUNCTIONs, error handling,
reparses procedures at each call (no caching), etc, etc.
Certainly buggy too, but procedures can actually be created and called....
sql/Makefile.am:
Added SP files.
sql/item.cc:
Added this*_item() methods for Item_splocal. (SP local variable)
sql/item.h:
Added this*_item() methods for SPs in Item, and the new Item_splocal
class (SP local variable).
sql/lex.h:
Added new symbols for SPs. (Note: SPSET is temporary and will go away later.)
sql/sql_class.cc:
Initialize SP runtime context in THD.
sql/sql_class.h:
Add SP runtime context to THD.
sql/sql_lex.cc:
Init. buf pointer to beginning of command (needed by SPs).
Also initialize SP head and parse time context.
sql/sql_lex.h:
New SQLCOM_ tags for SPs, and added pointer to beginning of command pointer and
SP head and parse-time context to LEX.
sql/sql_parse.cc:
Added SQLCOM_CREATE_PROCEDURE, _CALL, _ALTER_PROCEDURE and _DROP_PROCEDURE cases.
(Still rudimentary and lacking proper error handling...)
sql/sql_yacc.yy:
Lots and lots of additions for SPs...
(Still even more missing, and no error messages...)
2002-12-08 19:59:22 +01:00
|
|
|
}
|
|
|
|
|
2013-06-19 13:32:14 +02:00
|
|
|
|
|
|
|
sp_pcontext::~sp_pcontext()
|
Simplistic, experimental framework for Stored Procedures (SPs).
Implements creation and dropping of PROCEDUREs, IN, OUT, and INOUT parameters,
single-statement procedures, rudimentary multi-statement (begin-end) prodedures
(when the client can handle it), and local variables.
Missing most of the embedded SQL language, all attributes, FUNCTIONs, error handling,
reparses procedures at each call (no caching), etc, etc.
Certainly buggy too, but procedures can actually be created and called....
sql/Makefile.am:
Added SP files.
sql/item.cc:
Added this*_item() methods for Item_splocal. (SP local variable)
sql/item.h:
Added this*_item() methods for SPs in Item, and the new Item_splocal
class (SP local variable).
sql/lex.h:
Added new symbols for SPs. (Note: SPSET is temporary and will go away later.)
sql/sql_class.cc:
Initialize SP runtime context in THD.
sql/sql_class.h:
Add SP runtime context to THD.
sql/sql_lex.cc:
Init. buf pointer to beginning of command (needed by SPs).
Also initialize SP head and parse time context.
sql/sql_lex.h:
New SQLCOM_ tags for SPs, and added pointer to beginning of command pointer and
SP head and parse-time context to LEX.
sql/sql_parse.cc:
Added SQLCOM_CREATE_PROCEDURE, _CALL, _ALTER_PROCEDURE and _DROP_PROCEDURE cases.
(Still rudimentary and lacking proper error handling...)
sql/sql_yacc.yy:
Lots and lots of additions for SPs...
(Still even more missing, and no error messages...)
2002-12-08 19:59:22 +01:00
|
|
|
{
|
2013-07-21 16:39:19 +02:00
|
|
|
for (size_t i= 0; i < m_children.elements(); ++i)
|
2013-06-19 13:32:14 +02:00
|
|
|
delete m_children.at(i);
|
Simplistic, experimental framework for Stored Procedures (SPs).
Implements creation and dropping of PROCEDUREs, IN, OUT, and INOUT parameters,
single-statement procedures, rudimentary multi-statement (begin-end) prodedures
(when the client can handle it), and local variables.
Missing most of the embedded SQL language, all attributes, FUNCTIONs, error handling,
reparses procedures at each call (no caching), etc, etc.
Certainly buggy too, but procedures can actually be created and called....
sql/Makefile.am:
Added SP files.
sql/item.cc:
Added this*_item() methods for Item_splocal. (SP local variable)
sql/item.h:
Added this*_item() methods for SPs in Item, and the new Item_splocal
class (SP local variable).
sql/lex.h:
Added new symbols for SPs. (Note: SPSET is temporary and will go away later.)
sql/sql_class.cc:
Initialize SP runtime context in THD.
sql/sql_class.h:
Add SP runtime context to THD.
sql/sql_lex.cc:
Init. buf pointer to beginning of command (needed by SPs).
Also initialize SP head and parse time context.
sql/sql_lex.h:
New SQLCOM_ tags for SPs, and added pointer to beginning of command pointer and
SP head and parse-time context to LEX.
sql/sql_parse.cc:
Added SQLCOM_CREATE_PROCEDURE, _CALL, _ALTER_PROCEDURE and _DROP_PROCEDURE cases.
(Still rudimentary and lacking proper error handling...)
sql/sql_yacc.yy:
Lots and lots of additions for SPs...
(Still even more missing, and no error messages...)
2002-12-08 19:59:22 +01:00
|
|
|
}
|
|
|
|
|
2013-06-19 13:32:14 +02:00
|
|
|
|
|
|
|
sp_pcontext *sp_pcontext::push_context(THD *thd, sp_pcontext::enum_scope scope)
|
Various bug fixes:
- Duplicate parameters/variables, conditions and cursors (not allowed).
- ITERATE in labelled BEGIN-END (not allowed).
- Missing SQLSTATE [VALUE] keywords in CONDITION/HANDLER declaration (added).
- Empty BEGIN-END (now allowed).
- End label (now optional).
include/mysqld_error.h:
New error code for duplicate things (vars et al) in SPs.
mysql-test/r/sp-error.result:
New error tests for ITERATE in begin-end block and duplicate variables,
conditions and cursors.
mysql-test/r/sp.result:
New tests for empty begin-end blocks, overriding local variables outside scope
only, leave a begin-end block, and SQLSTATE [VALUE] words for CONDITION/HANDLER
declarations.
mysql-test/t/sp-error.test:
New error tests for ITERATE in begin-end block and duplicate variables,
conditions and cursors.
mysql-test/t/sp.test:
New tests for empty begin-end blocks, overriding local variables outside scope
only, leave a begin-end block, and SQLSTATE [VALUE] words for CONDITION/HANDLER
declarations.
sql/lex.h:
New SQLSTATE keyword.
sql/share/czech/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/danish/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/dutch/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/english/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/estonian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/french/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/german/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/greek/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/hungarian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/italian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/japanese/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/korean/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/norwegian-ny/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/norwegian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/polish/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/portuguese/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/romanian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/russian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/serbian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/slovak/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/spanish/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/swedish/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/ukrainian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/sp_pcontext.cc:
Keep track on scope limits for error checking of duplicate variables,
conditions and cursors.
sql/sp_pcontext.h:
Keep track on scope limits for error checking of duplicate variables,
conditions and cursors.
Also need to flag BEGIN labels to check for illegal ITERATEs.
sql/sql_yacc.yy:
End-labels in SPs loop and begin-end blocks are now optional.
SQLSTATE [VALUE] added to syntax for sqlstates.
Check for duplicate variable, condition and cursor declarations, but
only in the same scope.
Empty BEGIN-END statements now allowed.
Check if ITERATE is referring to a BEGIN label.
2003-11-13 19:34:56 +01:00
|
|
|
{
|
2013-06-19 13:32:14 +02:00
|
|
|
sp_pcontext *child= new (thd->mem_root) sp_pcontext(this, scope);
|
2004-08-26 12:54:30 +02:00
|
|
|
|
|
|
|
if (child)
|
2013-06-19 13:32:14 +02:00
|
|
|
m_children.append(child);
|
2004-08-26 12:54:30 +02:00
|
|
|
return child;
|
Various bug fixes:
- Duplicate parameters/variables, conditions and cursors (not allowed).
- ITERATE in labelled BEGIN-END (not allowed).
- Missing SQLSTATE [VALUE] keywords in CONDITION/HANDLER declaration (added).
- Empty BEGIN-END (now allowed).
- End label (now optional).
include/mysqld_error.h:
New error code for duplicate things (vars et al) in SPs.
mysql-test/r/sp-error.result:
New error tests for ITERATE in begin-end block and duplicate variables,
conditions and cursors.
mysql-test/r/sp.result:
New tests for empty begin-end blocks, overriding local variables outside scope
only, leave a begin-end block, and SQLSTATE [VALUE] words for CONDITION/HANDLER
declarations.
mysql-test/t/sp-error.test:
New error tests for ITERATE in begin-end block and duplicate variables,
conditions and cursors.
mysql-test/t/sp.test:
New tests for empty begin-end blocks, overriding local variables outside scope
only, leave a begin-end block, and SQLSTATE [VALUE] words for CONDITION/HANDLER
declarations.
sql/lex.h:
New SQLSTATE keyword.
sql/share/czech/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/danish/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/dutch/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/english/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/estonian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/french/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/german/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/greek/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/hungarian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/italian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/japanese/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/korean/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/norwegian-ny/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/norwegian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/polish/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/portuguese/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/romanian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/russian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/serbian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/slovak/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/spanish/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/swedish/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/ukrainian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/sp_pcontext.cc:
Keep track on scope limits for error checking of duplicate variables,
conditions and cursors.
sql/sp_pcontext.h:
Keep track on scope limits for error checking of duplicate variables,
conditions and cursors.
Also need to flag BEGIN labels to check for illegal ITERATEs.
sql/sql_yacc.yy:
End-labels in SPs loop and begin-end blocks are now optional.
SQLSTATE [VALUE] added to syntax for sqlstates.
Check for duplicate variable, condition and cursor declarations, but
only in the same scope.
Empty BEGIN-END statements now allowed.
Check if ITERATE is referring to a BEGIN label.
2003-11-13 19:34:56 +01:00
|
|
|
}
|
|
|
|
|
2013-06-19 13:32:14 +02:00
|
|
|
|
2017-02-14 14:43:11 +01:00
|
|
|
bool cmp_labels(sp_label *a, sp_label *b)
|
|
|
|
{
|
2017-06-18 13:00:28 +02:00
|
|
|
return (lex_string_cmp(system_charset_info, &a->name, &b->name) == 0 &&
|
|
|
|
a->type == b->type);
|
2017-02-14 14:43:11 +01:00
|
|
|
}
|
|
|
|
|
2013-06-19 13:32:14 +02:00
|
|
|
sp_pcontext *sp_pcontext::pop_context()
|
Various bug fixes:
- Duplicate parameters/variables, conditions and cursors (not allowed).
- ITERATE in labelled BEGIN-END (not allowed).
- Missing SQLSTATE [VALUE] keywords in CONDITION/HANDLER declaration (added).
- Empty BEGIN-END (now allowed).
- End label (now optional).
include/mysqld_error.h:
New error code for duplicate things (vars et al) in SPs.
mysql-test/r/sp-error.result:
New error tests for ITERATE in begin-end block and duplicate variables,
conditions and cursors.
mysql-test/r/sp.result:
New tests for empty begin-end blocks, overriding local variables outside scope
only, leave a begin-end block, and SQLSTATE [VALUE] words for CONDITION/HANDLER
declarations.
mysql-test/t/sp-error.test:
New error tests for ITERATE in begin-end block and duplicate variables,
conditions and cursors.
mysql-test/t/sp.test:
New tests for empty begin-end blocks, overriding local variables outside scope
only, leave a begin-end block, and SQLSTATE [VALUE] words for CONDITION/HANDLER
declarations.
sql/lex.h:
New SQLSTATE keyword.
sql/share/czech/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/danish/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/dutch/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/english/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/estonian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/french/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/german/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/greek/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/hungarian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/italian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/japanese/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/korean/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/norwegian-ny/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/norwegian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/polish/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/portuguese/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/romanian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/russian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/serbian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/slovak/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/spanish/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/swedish/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/ukrainian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/sp_pcontext.cc:
Keep track on scope limits for error checking of duplicate variables,
conditions and cursors.
sql/sp_pcontext.h:
Keep track on scope limits for error checking of duplicate variables,
conditions and cursors.
Also need to flag BEGIN labels to check for illegal ITERATEs.
sql/sql_yacc.yy:
End-labels in SPs loop and begin-end blocks are now optional.
SQLSTATE [VALUE] added to syntax for sqlstates.
Check for duplicate variable, condition and cursor declarations, but
only in the same scope.
Empty BEGIN-END statements now allowed.
Check if ITERATE is referring to a BEGIN label.
2003-11-13 19:34:56 +01:00
|
|
|
{
|
2006-04-07 16:53:15 +02:00
|
|
|
m_parent->m_max_var_index+= m_max_var_index;
|
2004-08-26 12:54:30 +02:00
|
|
|
|
2013-06-19 13:32:14 +02:00
|
|
|
uint submax= max_cursor_index();
|
2006-04-07 16:53:15 +02:00
|
|
|
if (submax > m_parent->m_max_cursor_index)
|
|
|
|
m_parent->m_max_cursor_index= submax;
|
2005-12-07 15:01:17 +01:00
|
|
|
|
|
|
|
if (m_num_case_exprs > m_parent->m_num_case_exprs)
|
|
|
|
m_parent->m_num_case_exprs= m_num_case_exprs;
|
|
|
|
|
2017-02-14 14:43:11 +01:00
|
|
|
/*
|
|
|
|
** Push unresolved goto label to parent context
|
|
|
|
*/
|
|
|
|
sp_label *label;
|
|
|
|
List_iterator_fast<sp_label> li(m_goto_labels);
|
|
|
|
while ((label= li++))
|
|
|
|
{
|
|
|
|
if (label->ip == 0)
|
|
|
|
{
|
|
|
|
m_parent->m_goto_labels.add_unique(label, &cmp_labels);
|
|
|
|
}
|
|
|
|
}
|
2004-08-26 12:54:30 +02:00
|
|
|
return m_parent;
|
2004-08-17 20:20:58 +02:00
|
|
|
}
|
|
|
|
|
2013-06-19 13:32:14 +02:00
|
|
|
|
|
|
|
uint sp_pcontext::diff_handlers(const sp_pcontext *ctx, bool exclusive) const
|
2004-08-17 20:20:58 +02:00
|
|
|
{
|
2004-08-26 12:54:30 +02:00
|
|
|
uint n= 0;
|
2013-06-19 13:32:14 +02:00
|
|
|
const sp_pcontext *pctx= this;
|
|
|
|
const sp_pcontext *last_ctx= NULL;
|
2004-08-17 20:20:58 +02:00
|
|
|
|
2004-08-26 12:54:30 +02:00
|
|
|
while (pctx && pctx != ctx)
|
2004-08-17 20:20:58 +02:00
|
|
|
{
|
2018-02-06 13:55:58 +01:00
|
|
|
n+= (uint)pctx->m_handlers.elements();
|
2006-02-15 12:11:29 +01:00
|
|
|
last_ctx= pctx;
|
2004-08-26 12:54:30 +02:00
|
|
|
pctx= pctx->parent_context();
|
2004-08-17 20:20:58 +02:00
|
|
|
}
|
2004-08-26 12:54:30 +02:00
|
|
|
if (pctx)
|
2018-02-06 13:55:58 +01:00
|
|
|
return (exclusive && last_ctx ? n -(uint) last_ctx->m_handlers.elements() : n);
|
2004-08-26 12:54:30 +02:00
|
|
|
return 0; // Didn't find ctx
|
|
|
|
}
|
|
|
|
|
2013-06-19 13:32:14 +02:00
|
|
|
|
|
|
|
uint sp_pcontext::diff_cursors(const sp_pcontext *ctx, bool exclusive) const
|
2004-08-26 12:54:30 +02:00
|
|
|
{
|
2006-02-15 12:11:29 +01:00
|
|
|
uint n= 0;
|
2013-06-19 13:32:14 +02:00
|
|
|
const sp_pcontext *pctx= this;
|
|
|
|
const sp_pcontext *last_ctx= NULL;
|
2004-08-26 12:54:30 +02:00
|
|
|
|
|
|
|
while (pctx && pctx != ctx)
|
2006-02-15 12:11:29 +01:00
|
|
|
{
|
2018-02-06 13:55:58 +01:00
|
|
|
n+= (uint)pctx->m_cursors.elements();
|
2006-02-15 12:11:29 +01:00
|
|
|
last_ctx= pctx;
|
2004-08-26 12:54:30 +02:00
|
|
|
pctx= pctx->parent_context();
|
2006-02-15 12:11:29 +01:00
|
|
|
}
|
2004-08-26 12:54:30 +02:00
|
|
|
if (pctx)
|
2018-02-06 13:55:58 +01:00
|
|
|
return (exclusive && last_ctx ? (uint)(n - last_ctx->m_cursors.elements()) : n);
|
2004-08-26 12:54:30 +02:00
|
|
|
return 0; // Didn't find ctx
|
Various bug fixes:
- Duplicate parameters/variables, conditions and cursors (not allowed).
- ITERATE in labelled BEGIN-END (not allowed).
- Missing SQLSTATE [VALUE] keywords in CONDITION/HANDLER declaration (added).
- Empty BEGIN-END (now allowed).
- End label (now optional).
include/mysqld_error.h:
New error code for duplicate things (vars et al) in SPs.
mysql-test/r/sp-error.result:
New error tests for ITERATE in begin-end block and duplicate variables,
conditions and cursors.
mysql-test/r/sp.result:
New tests for empty begin-end blocks, overriding local variables outside scope
only, leave a begin-end block, and SQLSTATE [VALUE] words for CONDITION/HANDLER
declarations.
mysql-test/t/sp-error.test:
New error tests for ITERATE in begin-end block and duplicate variables,
conditions and cursors.
mysql-test/t/sp.test:
New tests for empty begin-end blocks, overriding local variables outside scope
only, leave a begin-end block, and SQLSTATE [VALUE] words for CONDITION/HANDLER
declarations.
sql/lex.h:
New SQLSTATE keyword.
sql/share/czech/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/danish/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/dutch/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/english/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/estonian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/french/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/german/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/greek/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/hungarian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/italian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/japanese/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/korean/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/norwegian-ny/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/norwegian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/polish/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/portuguese/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/romanian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/russian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/serbian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/slovak/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/spanish/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/swedish/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/ukrainian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/sp_pcontext.cc:
Keep track on scope limits for error checking of duplicate variables,
conditions and cursors.
sql/sp_pcontext.h:
Keep track on scope limits for error checking of duplicate variables,
conditions and cursors.
Also need to flag BEGIN labels to check for illegal ITERATEs.
sql/sql_yacc.yy:
End-labels in SPs loop and begin-end blocks are now optional.
SQLSTATE [VALUE] added to syntax for sqlstates.
Check for duplicate variable, condition and cursor declarations, but
only in the same scope.
Empty BEGIN-END statements now allowed.
Check if ITERATE is referring to a BEGIN label.
2003-11-13 19:34:56 +01:00
|
|
|
}
|
|
|
|
|
2013-06-19 13:32:14 +02:00
|
|
|
|
2017-04-23 18:39:57 +02:00
|
|
|
sp_variable *sp_pcontext::find_variable(const LEX_CSTRING *name,
|
2013-06-19 13:32:14 +02:00
|
|
|
bool current_scope_only) const
|
Simplistic, experimental framework for Stored Procedures (SPs).
Implements creation and dropping of PROCEDUREs, IN, OUT, and INOUT parameters,
single-statement procedures, rudimentary multi-statement (begin-end) prodedures
(when the client can handle it), and local variables.
Missing most of the embedded SQL language, all attributes, FUNCTIONs, error handling,
reparses procedures at each call (no caching), etc, etc.
Certainly buggy too, but procedures can actually be created and called....
sql/Makefile.am:
Added SP files.
sql/item.cc:
Added this*_item() methods for Item_splocal. (SP local variable)
sql/item.h:
Added this*_item() methods for SPs in Item, and the new Item_splocal
class (SP local variable).
sql/lex.h:
Added new symbols for SPs. (Note: SPSET is temporary and will go away later.)
sql/sql_class.cc:
Initialize SP runtime context in THD.
sql/sql_class.h:
Add SP runtime context to THD.
sql/sql_lex.cc:
Init. buf pointer to beginning of command (needed by SPs).
Also initialize SP head and parse time context.
sql/sql_lex.h:
New SQLCOM_ tags for SPs, and added pointer to beginning of command pointer and
SP head and parse-time context to LEX.
sql/sql_parse.cc:
Added SQLCOM_CREATE_PROCEDURE, _CALL, _ALTER_PROCEDURE and _DROP_PROCEDURE cases.
(Still rudimentary and lacking proper error handling...)
sql/sql_yacc.yy:
Lots and lots of additions for SPs...
(Still even more missing, and no error messages...)
2002-12-08 19:59:22 +01:00
|
|
|
{
|
2018-02-06 13:55:58 +01:00
|
|
|
size_t i= m_vars.elements() - m_pboundary;
|
Various bug fixes:
- Duplicate parameters/variables, conditions and cursors (not allowed).
- ITERATE in labelled BEGIN-END (not allowed).
- Missing SQLSTATE [VALUE] keywords in CONDITION/HANDLER declaration (added).
- Empty BEGIN-END (now allowed).
- End label (now optional).
include/mysqld_error.h:
New error code for duplicate things (vars et al) in SPs.
mysql-test/r/sp-error.result:
New error tests for ITERATE in begin-end block and duplicate variables,
conditions and cursors.
mysql-test/r/sp.result:
New tests for empty begin-end blocks, overriding local variables outside scope
only, leave a begin-end block, and SQLSTATE [VALUE] words for CONDITION/HANDLER
declarations.
mysql-test/t/sp-error.test:
New error tests for ITERATE in begin-end block and duplicate variables,
conditions and cursors.
mysql-test/t/sp.test:
New tests for empty begin-end blocks, overriding local variables outside scope
only, leave a begin-end block, and SQLSTATE [VALUE] words for CONDITION/HANDLER
declarations.
sql/lex.h:
New SQLSTATE keyword.
sql/share/czech/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/danish/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/dutch/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/english/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/estonian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/french/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/german/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/greek/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/hungarian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/italian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/japanese/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/korean/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/norwegian-ny/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/norwegian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/polish/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/portuguese/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/romanian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/russian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/serbian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/slovak/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/spanish/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/swedish/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/ukrainian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/sp_pcontext.cc:
Keep track on scope limits for error checking of duplicate variables,
conditions and cursors.
sql/sp_pcontext.h:
Keep track on scope limits for error checking of duplicate variables,
conditions and cursors.
Also need to flag BEGIN labels to check for illegal ITERATEs.
sql/sql_yacc.yy:
End-labels in SPs loop and begin-end blocks are now optional.
SQLSTATE [VALUE] added to syntax for sqlstates.
Check for duplicate variable, condition and cursor declarations, but
only in the same scope.
Empty BEGIN-END statements now allowed.
Check if ITERATE is referring to a BEGIN label.
2003-11-13 19:34:56 +01:00
|
|
|
|
2004-08-26 12:54:30 +02:00
|
|
|
while (i--)
|
Simplistic, experimental framework for Stored Procedures (SPs).
Implements creation and dropping of PROCEDUREs, IN, OUT, and INOUT parameters,
single-statement procedures, rudimentary multi-statement (begin-end) prodedures
(when the client can handle it), and local variables.
Missing most of the embedded SQL language, all attributes, FUNCTIONs, error handling,
reparses procedures at each call (no caching), etc, etc.
Certainly buggy too, but procedures can actually be created and called....
sql/Makefile.am:
Added SP files.
sql/item.cc:
Added this*_item() methods for Item_splocal. (SP local variable)
sql/item.h:
Added this*_item() methods for SPs in Item, and the new Item_splocal
class (SP local variable).
sql/lex.h:
Added new symbols for SPs. (Note: SPSET is temporary and will go away later.)
sql/sql_class.cc:
Initialize SP runtime context in THD.
sql/sql_class.h:
Add SP runtime context to THD.
sql/sql_lex.cc:
Init. buf pointer to beginning of command (needed by SPs).
Also initialize SP head and parse time context.
sql/sql_lex.h:
New SQLCOM_ tags for SPs, and added pointer to beginning of command pointer and
SP head and parse-time context to LEX.
sql/sql_parse.cc:
Added SQLCOM_CREATE_PROCEDURE, _CALL, _ALTER_PROCEDURE and _DROP_PROCEDURE cases.
(Still rudimentary and lacking proper error handling...)
sql/sql_yacc.yy:
Lots and lots of additions for SPs...
(Still even more missing, and no error messages...)
2002-12-08 19:59:22 +01:00
|
|
|
{
|
2013-06-19 13:32:14 +02:00
|
|
|
sp_variable *p= m_vars.at(i);
|
2003-03-20 11:57:05 +01:00
|
|
|
|
2020-01-26 17:27:13 +01:00
|
|
|
if (system_charset_info->strnncoll(name->str, name->length,
|
|
|
|
p->name.str, p->name.length) == 0)
|
2003-03-19 11:36:32 +01:00
|
|
|
{
|
2003-04-02 20:42:28 +02:00
|
|
|
return p;
|
2003-03-19 11:36:32 +01:00
|
|
|
}
|
Simplistic, experimental framework for Stored Procedures (SPs).
Implements creation and dropping of PROCEDUREs, IN, OUT, and INOUT parameters,
single-statement procedures, rudimentary multi-statement (begin-end) prodedures
(when the client can handle it), and local variables.
Missing most of the embedded SQL language, all attributes, FUNCTIONs, error handling,
reparses procedures at each call (no caching), etc, etc.
Certainly buggy too, but procedures can actually be created and called....
sql/Makefile.am:
Added SP files.
sql/item.cc:
Added this*_item() methods for Item_splocal. (SP local variable)
sql/item.h:
Added this*_item() methods for SPs in Item, and the new Item_splocal
class (SP local variable).
sql/lex.h:
Added new symbols for SPs. (Note: SPSET is temporary and will go away later.)
sql/sql_class.cc:
Initialize SP runtime context in THD.
sql/sql_class.h:
Add SP runtime context to THD.
sql/sql_lex.cc:
Init. buf pointer to beginning of command (needed by SPs).
Also initialize SP head and parse time context.
sql/sql_lex.h:
New SQLCOM_ tags for SPs, and added pointer to beginning of command pointer and
SP head and parse-time context to LEX.
sql/sql_parse.cc:
Added SQLCOM_CREATE_PROCEDURE, _CALL, _ALTER_PROCEDURE and _DROP_PROCEDURE cases.
(Still rudimentary and lacking proper error handling...)
sql/sql_yacc.yy:
Lots and lots of additions for SPs...
(Still even more missing, and no error messages...)
2002-12-08 19:59:22 +01:00
|
|
|
}
|
2013-06-19 13:32:14 +02:00
|
|
|
|
|
|
|
return (!current_scope_only && m_parent) ?
|
|
|
|
m_parent->find_variable(name, false) :
|
|
|
|
NULL;
|
Simplistic, experimental framework for Stored Procedures (SPs).
Implements creation and dropping of PROCEDUREs, IN, OUT, and INOUT parameters,
single-statement procedures, rudimentary multi-statement (begin-end) prodedures
(when the client can handle it), and local variables.
Missing most of the embedded SQL language, all attributes, FUNCTIONs, error handling,
reparses procedures at each call (no caching), etc, etc.
Certainly buggy too, but procedures can actually be created and called....
sql/Makefile.am:
Added SP files.
sql/item.cc:
Added this*_item() methods for Item_splocal. (SP local variable)
sql/item.h:
Added this*_item() methods for SPs in Item, and the new Item_splocal
class (SP local variable).
sql/lex.h:
Added new symbols for SPs. (Note: SPSET is temporary and will go away later.)
sql/sql_class.cc:
Initialize SP runtime context in THD.
sql/sql_class.h:
Add SP runtime context to THD.
sql/sql_lex.cc:
Init. buf pointer to beginning of command (needed by SPs).
Also initialize SP head and parse time context.
sql/sql_lex.h:
New SQLCOM_ tags for SPs, and added pointer to beginning of command pointer and
SP head and parse-time context to LEX.
sql/sql_parse.cc:
Added SQLCOM_CREATE_PROCEDURE, _CALL, _ALTER_PROCEDURE and _DROP_PROCEDURE cases.
(Still rudimentary and lacking proper error handling...)
sql/sql_yacc.yy:
Lots and lots of additions for SPs...
(Still even more missing, and no error messages...)
2002-12-08 19:59:22 +01:00
|
|
|
}
|
|
|
|
|
2013-06-19 13:32:14 +02:00
|
|
|
|
MDEV-12441 Variables declared after cursors with parameters lose values
Parse context frames (sp_pcontext) can have holes in variable run-time offsets,
the missing offsets reside on the children contexts in such cases.
Example:
CREATE PROCEDURE p1() AS
x0 INT:=100; -- context 0, position 0, run-time 0
CURSOR cur(
p0 INT, -- context 1, position 0, run-time 1
p1 INT -- context 1, position 1, run-time 2
) IS SELECT p0, p1;
x1 INT:=101; -- context 0, position 1, run-time 3
BEGIN
...
END;
Fixing a few methods to take this into account:
- sp_pcontext::find_variable()
- sp_pcontext::retrieve_field_definitions()
- LEX::sp_variable_declarations_init()
- LEX::sp_variable_declarations_finalize()
- LEX::sp_variable_declarations_rowtype_finalize()
- LEX::sp_variable_declarations_with_ref_finalize()
Adding a convenience method:
sp_pcontext::get_last_context_variable(uint offset_from_the_end);
to access variables from the end, rather than from the beginning.
This helps to loop through the context variable array (m_vars)
on the fragment that does not have any holes.
Additionally, renaming sp_pcontext::find_context_variable() to
sp_pcontext::get_context_variable(). This method simply returns
the variable by its index. So let's rename to avoid assumptions
that some heavy lookup is going on inside.
2017-04-05 08:52:31 +02:00
|
|
|
/*
|
|
|
|
Find a variable by its run-time offset.
|
|
|
|
If the variable with a desired run-time offset is not found in this
|
|
|
|
context frame, it's recursively searched on parent context frames.
|
|
|
|
|
|
|
|
Note, context frames can have holes:
|
|
|
|
CREATE PROCEDURE p1() AS
|
|
|
|
x0 INT:=100;
|
|
|
|
CURSOR cur(p0 INT, p1 INT) IS SELECT p0, p1;
|
|
|
|
x1 INT:=101;
|
|
|
|
BEGIN
|
|
|
|
...
|
|
|
|
END;
|
|
|
|
The variables (x0 and x1) and the cursor parameters (p0 and p1)
|
|
|
|
reside in separate parse context frames.
|
|
|
|
|
|
|
|
The variables reside on the top level parse context frame:
|
|
|
|
- x0 has frame offset 0 and run-time offset 0
|
|
|
|
- x1 has frame offset 1 and run-time offset 3
|
|
|
|
|
|
|
|
The cursor parameters reside on the second level parse context frame:
|
|
|
|
- p0 has frame offset 0 and run-time offset 1
|
|
|
|
- p1 has frame offset 1 and run-time offset 2
|
|
|
|
|
|
|
|
Run-time offsets on a frame can have holes, but offsets monotonocally grow,
|
|
|
|
so run-time offsets of all variables are not greater than the run-time offset
|
|
|
|
of the very last variable in this frame.
|
|
|
|
*/
|
2013-06-19 13:32:14 +02:00
|
|
|
sp_variable *sp_pcontext::find_variable(uint offset) const
|
Background:
Since long, the compiled code of stored routines has been printed in the trace file
when starting mysqld with the "--debug" flag. (At creation time only, and only in
debug builds of course.) This has been helpful when debugging stored procedure
execution, but it's a bit awkward to use. Also, the printing of some of the
instructions is a bit terse, in particular for sp_instr_stmt where only the command
code was printed.
This improves the printout of several of the instructions, and adds the debugging-
only commands "show procedure code <name>" and "show function code <name>".
(In non-debug builds they are not available.)
sql/lex.h:
New symbol for debug-only command (e.g. show procedure code).
sql/sp_head.cc:
Fixed some minor debug-mode bugs in show_create_*().
New method for debugging: sp_head::show_routine_code() - returns the "assembly code"
for a stored routine as a result set.
Improved the print() methods for many sp_instr* classes, particularly for
sp_instr_stmt where the query string is printed as well (up to a max length, just
to give a hint of which statement it is). Also print the names of variables and
cursors in some instruction.
sql/sp_head.h:
New debugging-only method in sp_head: show_routine_code().
Added offset member to sp_instr_cpush for improved debug printing.
sql/sp_pcontext.cc:
Moved find_pvar(uint i) method from sp_pcontext.h, and made it work for all
frames, not just the first one. (For debugging purposes)
Added a similar find_cursor(uint i, ...) method, for debugging.
sql/sp_pcontext.h:
Moved find_pvar(uint i) method to sp_pcontext.cc.
Added a similar find_cursor(uint i, ...) method, for debugging.
sql/sql_lex.h:
Added new sql_command codes for debugging.
sql/sql_parse.cc:
Added new commands for debugging, e.g. "show procedure code".
sql/sql_yacc.yy:
Added new commands for debugging purposes:
"show procedure code ..." and "show function code ...".
These are only enabled in debug builds, otherwise they result in a syntax error.
(I.e. they don't exist)
2005-11-17 11:11:48 +01:00
|
|
|
{
|
MDEV-12441 Variables declared after cursors with parameters lose values
Parse context frames (sp_pcontext) can have holes in variable run-time offsets,
the missing offsets reside on the children contexts in such cases.
Example:
CREATE PROCEDURE p1() AS
x0 INT:=100; -- context 0, position 0, run-time 0
CURSOR cur(
p0 INT, -- context 1, position 0, run-time 1
p1 INT -- context 1, position 1, run-time 2
) IS SELECT p0, p1;
x1 INT:=101; -- context 0, position 1, run-time 3
BEGIN
...
END;
Fixing a few methods to take this into account:
- sp_pcontext::find_variable()
- sp_pcontext::retrieve_field_definitions()
- LEX::sp_variable_declarations_init()
- LEX::sp_variable_declarations_finalize()
- LEX::sp_variable_declarations_rowtype_finalize()
- LEX::sp_variable_declarations_with_ref_finalize()
Adding a convenience method:
sp_pcontext::get_last_context_variable(uint offset_from_the_end);
to access variables from the end, rather than from the beginning.
This helps to loop through the context variable array (m_vars)
on the fragment that does not have any holes.
Additionally, renaming sp_pcontext::find_context_variable() to
sp_pcontext::get_context_variable(). This method simply returns
the variable by its index. So let's rename to avoid assumptions
that some heavy lookup is going on inside.
2017-04-05 08:52:31 +02:00
|
|
|
if (m_var_offset <= offset &&
|
|
|
|
m_vars.elements() &&
|
|
|
|
offset <= get_last_context_variable()->offset)
|
|
|
|
{
|
|
|
|
for (uint i= 0; i < m_vars.elements(); i++)
|
|
|
|
{
|
|
|
|
if (m_vars.at(i)->offset == offset)
|
|
|
|
return m_vars.at(i); // This frame
|
|
|
|
}
|
|
|
|
}
|
Background:
Since long, the compiled code of stored routines has been printed in the trace file
when starting mysqld with the "--debug" flag. (At creation time only, and only in
debug builds of course.) This has been helpful when debugging stored procedure
execution, but it's a bit awkward to use. Also, the printing of some of the
instructions is a bit terse, in particular for sp_instr_stmt where only the command
code was printed.
This improves the printout of several of the instructions, and adds the debugging-
only commands "show procedure code <name>" and "show function code <name>".
(In non-debug builds they are not available.)
sql/lex.h:
New symbol for debug-only command (e.g. show procedure code).
sql/sp_head.cc:
Fixed some minor debug-mode bugs in show_create_*().
New method for debugging: sp_head::show_routine_code() - returns the "assembly code"
for a stored routine as a result set.
Improved the print() methods for many sp_instr* classes, particularly for
sp_instr_stmt where the query string is printed as well (up to a max length, just
to give a hint of which statement it is). Also print the names of variables and
cursors in some instruction.
sql/sp_head.h:
New debugging-only method in sp_head: show_routine_code().
Added offset member to sp_instr_cpush for improved debug printing.
sql/sp_pcontext.cc:
Moved find_pvar(uint i) method from sp_pcontext.h, and made it work for all
frames, not just the first one. (For debugging purposes)
Added a similar find_cursor(uint i, ...) method, for debugging.
sql/sp_pcontext.h:
Moved find_pvar(uint i) method to sp_pcontext.cc.
Added a similar find_cursor(uint i, ...) method, for debugging.
sql/sql_lex.h:
Added new sql_command codes for debugging.
sql/sql_parse.cc:
Added new commands for debugging, e.g. "show procedure code".
sql/sql_yacc.yy:
Added new commands for debugging purposes:
"show procedure code ..." and "show function code ...".
These are only enabled in debug builds, otherwise they result in a syntax error.
(I.e. they don't exist)
2005-11-17 11:11:48 +01:00
|
|
|
|
2013-06-19 13:32:14 +02:00
|
|
|
return m_parent ?
|
|
|
|
m_parent->find_variable(offset) : // Some previous frame
|
|
|
|
NULL; // Index out of bounds
|
Background:
Since long, the compiled code of stored routines has been printed in the trace file
when starting mysqld with the "--debug" flag. (At creation time only, and only in
debug builds of course.) This has been helpful when debugging stored procedure
execution, but it's a bit awkward to use. Also, the printing of some of the
instructions is a bit terse, in particular for sp_instr_stmt where only the command
code was printed.
This improves the printout of several of the instructions, and adds the debugging-
only commands "show procedure code <name>" and "show function code <name>".
(In non-debug builds they are not available.)
sql/lex.h:
New symbol for debug-only command (e.g. show procedure code).
sql/sp_head.cc:
Fixed some minor debug-mode bugs in show_create_*().
New method for debugging: sp_head::show_routine_code() - returns the "assembly code"
for a stored routine as a result set.
Improved the print() methods for many sp_instr* classes, particularly for
sp_instr_stmt where the query string is printed as well (up to a max length, just
to give a hint of which statement it is). Also print the names of variables and
cursors in some instruction.
sql/sp_head.h:
New debugging-only method in sp_head: show_routine_code().
Added offset member to sp_instr_cpush for improved debug printing.
sql/sp_pcontext.cc:
Moved find_pvar(uint i) method from sp_pcontext.h, and made it work for all
frames, not just the first one. (For debugging purposes)
Added a similar find_cursor(uint i, ...) method, for debugging.
sql/sp_pcontext.h:
Moved find_pvar(uint i) method to sp_pcontext.cc.
Added a similar find_cursor(uint i, ...) method, for debugging.
sql/sql_lex.h:
Added new sql_command codes for debugging.
sql/sql_parse.cc:
Added new commands for debugging, e.g. "show procedure code".
sql/sql_yacc.yy:
Added new commands for debugging purposes:
"show procedure code ..." and "show function code ...".
These are only enabled in debug builds, otherwise they result in a syntax error.
(I.e. they don't exist)
2005-11-17 11:11:48 +01:00
|
|
|
}
|
|
|
|
|
2013-06-19 13:32:14 +02:00
|
|
|
|
2017-04-23 18:39:57 +02:00
|
|
|
sp_variable *sp_pcontext::add_variable(THD *thd, const LEX_CSTRING *name)
|
Simplistic, experimental framework for Stored Procedures (SPs).
Implements creation and dropping of PROCEDUREs, IN, OUT, and INOUT parameters,
single-statement procedures, rudimentary multi-statement (begin-end) prodedures
(when the client can handle it), and local variables.
Missing most of the embedded SQL language, all attributes, FUNCTIONs, error handling,
reparses procedures at each call (no caching), etc, etc.
Certainly buggy too, but procedures can actually be created and called....
sql/Makefile.am:
Added SP files.
sql/item.cc:
Added this*_item() methods for Item_splocal. (SP local variable)
sql/item.h:
Added this*_item() methods for SPs in Item, and the new Item_splocal
class (SP local variable).
sql/lex.h:
Added new symbols for SPs. (Note: SPSET is temporary and will go away later.)
sql/sql_class.cc:
Initialize SP runtime context in THD.
sql/sql_class.h:
Add SP runtime context to THD.
sql/sql_lex.cc:
Init. buf pointer to beginning of command (needed by SPs).
Also initialize SP head and parse time context.
sql/sql_lex.h:
New SQLCOM_ tags for SPs, and added pointer to beginning of command pointer and
SP head and parse-time context to LEX.
sql/sql_parse.cc:
Added SQLCOM_CREATE_PROCEDURE, _CALL, _ALTER_PROCEDURE and _DROP_PROCEDURE cases.
(Still rudimentary and lacking proper error handling...)
sql/sql_yacc.yy:
Lots and lots of additions for SPs...
(Still even more missing, and no error messages...)
2002-12-08 19:59:22 +01:00
|
|
|
{
|
2013-06-19 13:32:14 +02:00
|
|
|
sp_variable *p=
|
MDEV-12441 Variables declared after cursors with parameters lose values
Parse context frames (sp_pcontext) can have holes in variable run-time offsets,
the missing offsets reside on the children contexts in such cases.
Example:
CREATE PROCEDURE p1() AS
x0 INT:=100; -- context 0, position 0, run-time 0
CURSOR cur(
p0 INT, -- context 1, position 0, run-time 1
p1 INT -- context 1, position 1, run-time 2
) IS SELECT p0, p1;
x1 INT:=101; -- context 0, position 1, run-time 3
BEGIN
...
END;
Fixing a few methods to take this into account:
- sp_pcontext::find_variable()
- sp_pcontext::retrieve_field_definitions()
- LEX::sp_variable_declarations_init()
- LEX::sp_variable_declarations_finalize()
- LEX::sp_variable_declarations_rowtype_finalize()
- LEX::sp_variable_declarations_with_ref_finalize()
Adding a convenience method:
sp_pcontext::get_last_context_variable(uint offset_from_the_end);
to access variables from the end, rather than from the beginning.
This helps to loop through the context variable array (m_vars)
on the fragment that does not have any holes.
Additionally, renaming sp_pcontext::find_context_variable() to
sp_pcontext::get_context_variable(). This method simply returns
the variable by its index. So let's rename to avoid assumptions
that some heavy lookup is going on inside.
2017-04-05 08:52:31 +02:00
|
|
|
new (thd->mem_root) sp_variable(name, m_var_offset + m_max_var_index);
|
2003-04-02 20:42:28 +02:00
|
|
|
|
2005-12-07 15:01:17 +01:00
|
|
|
if (!p)
|
|
|
|
return NULL;
|
|
|
|
|
2006-04-07 16:53:15 +02:00
|
|
|
++m_max_var_index;
|
2005-12-07 15:01:17 +01:00
|
|
|
|
2013-06-19 13:32:14 +02:00
|
|
|
return m_vars.append(p) ? NULL : p;
|
Simplistic, experimental framework for Stored Procedures (SPs).
Implements creation and dropping of PROCEDUREs, IN, OUT, and INOUT parameters,
single-statement procedures, rudimentary multi-statement (begin-end) prodedures
(when the client can handle it), and local variables.
Missing most of the embedded SQL language, all attributes, FUNCTIONs, error handling,
reparses procedures at each call (no caching), etc, etc.
Certainly buggy too, but procedures can actually be created and called....
sql/Makefile.am:
Added SP files.
sql/item.cc:
Added this*_item() methods for Item_splocal. (SP local variable)
sql/item.h:
Added this*_item() methods for SPs in Item, and the new Item_splocal
class (SP local variable).
sql/lex.h:
Added new symbols for SPs. (Note: SPSET is temporary and will go away later.)
sql/sql_class.cc:
Initialize SP runtime context in THD.
sql/sql_class.h:
Add SP runtime context to THD.
sql/sql_lex.cc:
Init. buf pointer to beginning of command (needed by SPs).
Also initialize SP head and parse time context.
sql/sql_lex.h:
New SQLCOM_ tags for SPs, and added pointer to beginning of command pointer and
SP head and parse-time context to LEX.
sql/sql_parse.cc:
Added SQLCOM_CREATE_PROCEDURE, _CALL, _ALTER_PROCEDURE and _DROP_PROCEDURE cases.
(Still rudimentary and lacking proper error handling...)
sql/sql_yacc.yy:
Lots and lots of additions for SPs...
(Still even more missing, and no error messages...)
2002-12-08 19:59:22 +01:00
|
|
|
}
|
2002-12-11 14:24:29 +01:00
|
|
|
|
2017-04-23 18:39:57 +02:00
|
|
|
sp_label *sp_pcontext::push_label(THD *thd, const LEX_CSTRING *name, uint ip,
|
2017-02-14 14:43:11 +01:00
|
|
|
sp_label::enum_type type,
|
|
|
|
List<sp_label> *list)
|
2002-12-11 14:24:29 +01:00
|
|
|
{
|
2013-06-19 13:32:14 +02:00
|
|
|
sp_label *label=
|
2016-08-17 08:33:31 +02:00
|
|
|
new (thd->mem_root) sp_label(name, ip, type, this);
|
2002-12-11 14:24:29 +01:00
|
|
|
|
2013-06-19 13:32:14 +02:00
|
|
|
if (!label)
|
|
|
|
return NULL;
|
|
|
|
|
2017-02-14 14:43:11 +01:00
|
|
|
list->push_front(label, thd->mem_root);
|
2013-06-19 13:32:14 +02:00
|
|
|
|
|
|
|
return label;
|
2002-12-11 14:24:29 +01:00
|
|
|
}
|
|
|
|
|
2017-04-23 18:39:57 +02:00
|
|
|
sp_label *sp_pcontext::find_goto_label(const LEX_CSTRING *name, bool recusive)
|
2017-02-14 14:43:11 +01:00
|
|
|
{
|
|
|
|
List_iterator_fast<sp_label> li(m_goto_labels);
|
|
|
|
sp_label *lab;
|
|
|
|
|
|
|
|
while ((lab= li++))
|
|
|
|
{
|
2017-06-18 13:00:28 +02:00
|
|
|
if (lex_string_cmp(system_charset_info, name, &lab->name) == 0)
|
2017-02-14 14:43:11 +01:00
|
|
|
return lab;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!recusive)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/*
|
|
|
|
Note about exception handlers.
|
|
|
|
See SQL:2003 SQL/PSM (ISO/IEC 9075-4:2003),
|
|
|
|
section 13.1 <compound statement>,
|
|
|
|
syntax rule 4.
|
|
|
|
In short, a DECLARE HANDLER block can not refer
|
|
|
|
to labels from the parent context, as they are out of scope.
|
|
|
|
*/
|
|
|
|
if (m_scope == HANDLER_SCOPE && m_parent)
|
|
|
|
{
|
|
|
|
if (m_parent->m_parent)
|
|
|
|
{
|
|
|
|
// Skip the parent context
|
|
|
|
return m_parent->m_parent->find_goto_label(name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return m_parent && (m_scope == REGULAR_SCOPE) ?
|
|
|
|
m_parent->find_goto_label(name) :
|
|
|
|
NULL;
|
|
|
|
}
|
|
|
|
|
2013-06-19 13:32:14 +02:00
|
|
|
|
2017-04-23 18:39:57 +02:00
|
|
|
sp_label *sp_pcontext::find_label(const LEX_CSTRING *name)
|
2002-12-11 14:24:29 +01:00
|
|
|
{
|
2013-06-19 13:32:14 +02:00
|
|
|
List_iterator_fast<sp_label> li(m_labels);
|
|
|
|
sp_label *lab;
|
2002-12-11 14:24:29 +01:00
|
|
|
|
|
|
|
while ((lab= li++))
|
2013-06-19 13:32:14 +02:00
|
|
|
{
|
2017-06-18 13:00:28 +02:00
|
|
|
if (lex_string_cmp(system_charset_info, name, &lab->name) == 0)
|
2002-12-11 14:24:29 +01:00
|
|
|
return lab;
|
2013-06-19 13:32:14 +02:00
|
|
|
}
|
2002-12-11 14:24:29 +01:00
|
|
|
|
Bug#26503 (Illegal SQL exception handler code causes the server to crash)
Before this fix, the parser would accept illegal code in SQL exceptions
handlers, that later causes the runtime to crash when executing the code,
due to memory violations in the exception handler stack.
The root cause of the problem is instructions within an exception handler
that jumps to code located outside of the handler. This is illegal according
to the SQL 2003 standard, since labels located outside the handler are not
supposed to be visible (they are "out of scope"), so any instruction that
jumps to these labels, like ITERATE or LEAVE, should not parse.
The section of the standard that is relevant for this is :
SQL:2003 SQL/PSM (ISO/IEC 9075-4:2003)
section 13.1 <compound statement>,
syntax rule 4
<quote>
The scope of the <beginning label> is CS excluding every <SQL schema
statement> contained in CS and excluding every
<local handler declaration list> contained in CS. <beginning label> shall
not be equivalent to any other <beginning label>s within that scope.
</quote>
With this fix, the C++ class sp_pcontext, which represent the "parsing
context" tree (a.k.a symbol table) of a stored procedure, has been changed
as follows:
- constructors have been cleaned up, so that only building a root node for
the tree is public; building nodes inside a tree is not public.
- a new member, m_label_scope, indicates if a given syntactic context
belongs to a DECLARE HANDLER block,
- label resolution, in the method find_label(), has been changed to
implement the restriction of scope regarding labels used in a compound
statement.
The actions in the parser, when parsing the body of a SQL exception handler,
have been changed as follows:
- the implementation of an exception handler (DECLARE HANDLER) now creates
explicitly a new sp_pcontext, to isolate the code inside the handler from
the containing compound statement context.
- registering exception handlers as a result occurs in the parent context,
see the rule sp_hcond_element
- the code in sp_hcond_list has been cleaned up, to avoid code duplication
In addition, the flags IN_SIMPLE_CASE and IN_HANDLER, declared in sp_head.h
have been removed, since they are unused and broken by design (as seen with
Bug 19194 (Right recursion in parser for CASE causes excessive stack usage,
limitation), representing a stack in a single flag is not possible.
Tests in sp-error have been added to show that illegal constructs are now
rejected.
Tests in sp have been added for code coverage, to show that ITERATE or LEAVE
statements are legal when jumping to a label in scope, inside the body of
an exception handler.
mysql-test/r/sp-error.result:
SQL Exception handlers define a parsing context for label resolution.
mysql-test/r/sp.result:
SQL Exception handlers define a parsing context for label resolution.
mysql-test/t/sp-error.test:
SQL Exception handlers define a parsing context for label resolution.
mysql-test/t/sp.test:
SQL Exception handlers define a parsing context for label resolution.
sql/sp_head.cc:
Minor cleanup
sql/sp_head.h:
Minor cleanup
sql/sp_pcontext.cc:
SQL Exception handlers define a parsing context for label resolution.
sql/sp_pcontext.h:
SQL Exception handlers define a parsing context for label resolution.
sql/sql_yacc.yy:
SQL Exception handlers define a parsing context for label resolution.
2007-03-14 19:02:32 +01:00
|
|
|
/*
|
|
|
|
Note about exception handlers.
|
|
|
|
See SQL:2003 SQL/PSM (ISO/IEC 9075-4:2003),
|
|
|
|
section 13.1 <compound statement>,
|
|
|
|
syntax rule 4.
|
|
|
|
In short, a DECLARE HANDLER block can not refer
|
|
|
|
to labels from the parent context, as they are out of scope.
|
|
|
|
*/
|
2013-06-19 13:32:14 +02:00
|
|
|
return (m_parent && (m_scope == REGULAR_SCOPE)) ?
|
|
|
|
m_parent->find_label(name) :
|
|
|
|
NULL;
|
2002-12-11 14:24:29 +01:00
|
|
|
}
|
2003-09-16 14:26:08 +02:00
|
|
|
|
2013-06-19 13:32:14 +02:00
|
|
|
|
2016-08-17 08:33:31 +02:00
|
|
|
sp_label *sp_pcontext::find_label_current_loop_start()
|
|
|
|
{
|
|
|
|
List_iterator_fast<sp_label> li(m_labels);
|
|
|
|
sp_label *lab;
|
|
|
|
|
|
|
|
while ((lab= li++))
|
|
|
|
{
|
|
|
|
if (lab->type == sp_label::ITERATION)
|
|
|
|
return lab;
|
|
|
|
}
|
|
|
|
// See a comment in sp_pcontext::find_label()
|
|
|
|
return (m_parent && (m_scope == REGULAR_SCOPE)) ?
|
|
|
|
m_parent->find_label_current_loop_start() :
|
|
|
|
NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-06-19 13:32:14 +02:00
|
|
|
bool sp_pcontext::add_condition(THD *thd,
|
2017-04-23 18:39:57 +02:00
|
|
|
const LEX_CSTRING *name,
|
2013-06-19 13:32:14 +02:00
|
|
|
sp_condition_value *value)
|
2003-09-16 14:26:08 +02:00
|
|
|
{
|
2013-06-19 13:32:14 +02:00
|
|
|
sp_condition *p= new (thd->mem_root) sp_condition(name, value);
|
2003-09-16 14:26:08 +02:00
|
|
|
|
2008-11-21 14:38:42 +01:00
|
|
|
if (p == NULL)
|
2013-06-19 13:32:14 +02:00
|
|
|
return true;
|
|
|
|
|
|
|
|
return m_conditions.append(p);
|
2003-09-16 14:26:08 +02:00
|
|
|
}
|
|
|
|
|
2013-06-19 13:32:14 +02:00
|
|
|
|
2017-04-23 18:39:57 +02:00
|
|
|
sp_condition_value *sp_pcontext::find_condition(const LEX_CSTRING *name,
|
2013-06-19 13:32:14 +02:00
|
|
|
bool current_scope_only) const
|
2003-09-16 14:26:08 +02:00
|
|
|
{
|
2018-02-06 13:55:58 +01:00
|
|
|
size_t i= m_conditions.elements();
|
2003-09-16 14:26:08 +02:00
|
|
|
|
2004-08-26 12:54:30 +02:00
|
|
|
while (i--)
|
2003-09-16 14:26:08 +02:00
|
|
|
{
|
2013-06-19 13:32:14 +02:00
|
|
|
sp_condition *p= m_conditions.at(i);
|
2003-09-16 14:26:08 +02:00
|
|
|
|
2016-09-20 13:30:15 +02:00
|
|
|
if (p->eq_name(name))
|
2003-09-16 14:26:08 +02:00
|
|
|
{
|
2013-06-19 13:32:14 +02:00
|
|
|
return p->value;
|
2003-09-16 14:26:08 +02:00
|
|
|
}
|
|
|
|
}
|
2013-06-19 13:32:14 +02:00
|
|
|
|
|
|
|
return (!current_scope_only && m_parent) ?
|
|
|
|
m_parent->find_condition(name, false) :
|
|
|
|
NULL;
|
2003-09-16 14:26:08 +02:00
|
|
|
}
|
2003-10-10 16:57:21 +02:00
|
|
|
|
2018-11-09 14:08:13 +01:00
|
|
|
sp_condition_value *
|
|
|
|
sp_pcontext::find_declared_or_predefined_condition(THD *thd,
|
|
|
|
const LEX_CSTRING *name)
|
|
|
|
const
|
|
|
|
{
|
|
|
|
sp_condition_value *p= find_condition(name, false);
|
|
|
|
if (p)
|
|
|
|
return p;
|
|
|
|
if (thd->variables.sql_mode & MODE_ORACLE)
|
|
|
|
return find_predefined_condition(name);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-06-19 13:32:14 +02:00
|
|
|
|
2016-09-20 13:30:15 +02:00
|
|
|
static sp_condition_value
|
2016-09-27 11:22:38 +02:00
|
|
|
// Warnings
|
|
|
|
cond_no_data_found(ER_SP_FETCH_NO_DATA, "01000"),
|
|
|
|
// Errors
|
|
|
|
cond_invalid_cursor(ER_SP_CURSOR_NOT_OPEN, "24000"),
|
|
|
|
cond_dup_val_on_index(ER_DUP_ENTRY, "23000"),
|
2017-06-18 11:28:40 +02:00
|
|
|
cond_dup_val_on_index2(ER_DUP_ENTRY_WITH_KEY_NAME, "23000"),
|
2016-09-27 11:22:38 +02:00
|
|
|
cond_too_many_rows(ER_TOO_MANY_ROWS, "42000");
|
2016-09-20 13:30:15 +02:00
|
|
|
|
|
|
|
|
2016-09-27 08:13:08 +02:00
|
|
|
static sp_condition sp_predefined_conditions[]=
|
2016-09-20 13:30:15 +02:00
|
|
|
{
|
2016-09-27 11:22:38 +02:00
|
|
|
// Warnings
|
2018-01-08 14:33:23 +01:00
|
|
|
sp_condition(STRING_WITH_LEN("NO_DATA_FOUND"), &cond_no_data_found),
|
2016-09-27 11:22:38 +02:00
|
|
|
// Errors
|
2018-01-08 14:33:23 +01:00
|
|
|
sp_condition(STRING_WITH_LEN("INVALID_CURSOR"), &cond_invalid_cursor),
|
|
|
|
sp_condition(STRING_WITH_LEN("DUP_VAL_ON_INDEX"), &cond_dup_val_on_index),
|
|
|
|
sp_condition(STRING_WITH_LEN("DUP_VAL_ON_INDEX"), &cond_dup_val_on_index2),
|
|
|
|
sp_condition(STRING_WITH_LEN("TOO_MANY_ROWS"), &cond_too_many_rows)
|
2016-09-20 13:30:15 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
sp_condition_value *
|
2017-04-23 18:39:57 +02:00
|
|
|
sp_pcontext::find_predefined_condition(const LEX_CSTRING *name) const
|
2016-09-20 13:30:15 +02:00
|
|
|
{
|
|
|
|
for (uint i= 0; i < array_elements(sp_predefined_conditions) ; i++)
|
|
|
|
{
|
|
|
|
if (sp_predefined_conditions[i].eq_name(name))
|
|
|
|
return sp_predefined_conditions[i].value;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-06-19 13:32:14 +02:00
|
|
|
sp_handler *sp_pcontext::add_handler(THD *thd,
|
|
|
|
sp_handler::enum_type type)
|
2005-04-08 19:58:04 +02:00
|
|
|
{
|
2013-06-19 13:32:14 +02:00
|
|
|
sp_handler *h= new (thd->mem_root) sp_handler(type);
|
2005-04-08 19:58:04 +02:00
|
|
|
|
2013-06-19 13:32:14 +02:00
|
|
|
if (!h)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return m_handlers.append(h) ? NULL : h;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool sp_pcontext::check_duplicate_handler(
|
|
|
|
const sp_condition_value *cond_value) const
|
|
|
|
{
|
2013-07-21 16:39:19 +02:00
|
|
|
for (size_t i= 0; i < m_handlers.elements(); ++i)
|
2005-04-08 19:58:04 +02:00
|
|
|
{
|
2013-06-19 13:32:14 +02:00
|
|
|
sp_handler *h= m_handlers.at(i);
|
|
|
|
|
|
|
|
List_iterator_fast<sp_condition_value> li(h->condition_values);
|
|
|
|
sp_condition_value *cv;
|
2005-04-08 19:58:04 +02:00
|
|
|
|
2013-06-19 13:32:14 +02:00
|
|
|
while ((cv= li++))
|
2005-04-08 19:58:04 +02:00
|
|
|
{
|
2013-06-19 13:32:14 +02:00
|
|
|
if (cond_value->equals(cv))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-10-14 14:52:33 +02:00
|
|
|
bool sp_condition_value::matches(const Sql_condition_identity &value,
|
|
|
|
const sp_condition_value *found_cv) const
|
|
|
|
{
|
|
|
|
bool user_value_matched= !value.get_user_condition_value() ||
|
|
|
|
this == value.get_user_condition_value();
|
|
|
|
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case sp_condition_value::ERROR_CODE:
|
|
|
|
return user_value_matched &&
|
|
|
|
value.get_sql_errno() == get_sql_errno() &&
|
|
|
|
(!found_cv || found_cv->type > sp_condition_value::ERROR_CODE);
|
|
|
|
|
|
|
|
case sp_condition_value::SQLSTATE:
|
|
|
|
return user_value_matched &&
|
|
|
|
Sql_state::eq(&value) &&
|
|
|
|
(!found_cv || found_cv->type > sp_condition_value::SQLSTATE);
|
|
|
|
|
|
|
|
case sp_condition_value::WARNING:
|
|
|
|
return user_value_matched &&
|
|
|
|
(value.Sql_state::is_warning() ||
|
|
|
|
value.get_level() == Sql_condition::WARN_LEVEL_WARN) &&
|
|
|
|
!found_cv;
|
|
|
|
|
|
|
|
case sp_condition_value::NOT_FOUND:
|
|
|
|
return user_value_matched &&
|
|
|
|
value.Sql_state::is_not_found() &&
|
|
|
|
!found_cv;
|
|
|
|
|
|
|
|
case sp_condition_value::EXCEPTION:
|
|
|
|
/*
|
|
|
|
In sql_mode=ORACLE this construct should catch both errors and warnings:
|
|
|
|
EXCEPTION
|
|
|
|
WHEN OTHERS THEN ...;
|
|
|
|
E.g. NO_DATA_FOUND is more like a warning than an error,
|
|
|
|
and it should be caught.
|
|
|
|
|
|
|
|
We don't check user_value_matched here.
|
|
|
|
"WHEN OTHERS" catches all user defined exception.
|
|
|
|
*/
|
|
|
|
return (((current_thd->variables.sql_mode & MODE_ORACLE) ||
|
|
|
|
(value.Sql_state::is_exception() &&
|
|
|
|
value.get_level() == Sql_condition::WARN_LEVEL_ERROR)) &&
|
|
|
|
!found_cv);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-06-19 13:32:14 +02:00
|
|
|
sp_handler*
|
2016-10-14 14:52:33 +02:00
|
|
|
sp_pcontext::find_handler(const Sql_condition_identity &value) const
|
2013-06-19 13:32:14 +02:00
|
|
|
{
|
|
|
|
sp_handler *found_handler= NULL;
|
|
|
|
sp_condition_value *found_cv= NULL;
|
|
|
|
|
2013-07-21 16:39:19 +02:00
|
|
|
for (size_t i= 0; i < m_handlers.elements(); ++i)
|
2013-06-19 13:32:14 +02:00
|
|
|
{
|
|
|
|
sp_handler *h= m_handlers.at(i);
|
|
|
|
|
|
|
|
List_iterator_fast<sp_condition_value> li(h->condition_values);
|
|
|
|
sp_condition_value *cv;
|
|
|
|
|
|
|
|
while ((cv= li++))
|
|
|
|
{
|
2016-10-14 14:52:33 +02:00
|
|
|
if (cv->matches(value, found_cv))
|
2005-04-08 19:58:04 +02:00
|
|
|
{
|
2016-10-14 14:52:33 +02:00
|
|
|
found_cv= cv;
|
|
|
|
found_handler= h;
|
2005-04-08 19:58:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-06-19 13:32:14 +02:00
|
|
|
|
|
|
|
if (found_handler)
|
|
|
|
return found_handler;
|
|
|
|
|
|
|
|
|
|
|
|
// There is no appropriate handler in this parsing context. We need to look up
|
|
|
|
// in parent contexts. There might be two cases here:
|
|
|
|
//
|
|
|
|
// 1. The current context has REGULAR_SCOPE. That means, it's a simple
|
|
|
|
// BEGIN..END block:
|
|
|
|
// ...
|
|
|
|
// BEGIN
|
|
|
|
// ... # We're here.
|
|
|
|
// END
|
|
|
|
// ...
|
|
|
|
// In this case we simply call find_handler() on parent's context recursively.
|
|
|
|
//
|
|
|
|
// 2. The current context has HANDLER_SCOPE. That means, we're inside an
|
|
|
|
// SQL-handler block:
|
|
|
|
// ...
|
|
|
|
// DECLARE ... HANDLER FOR ...
|
|
|
|
// BEGIN
|
|
|
|
// ... # We're here.
|
|
|
|
// END
|
|
|
|
// ...
|
|
|
|
// In this case we can not just call parent's find_handler(), because
|
|
|
|
// parent's handler don't catch conditions from this scope. Instead, we should
|
|
|
|
// try to find first parent context (we might have nested handler
|
|
|
|
// declarations), which has REGULAR_SCOPE (i.e. which is regular BEGIN..END
|
|
|
|
// block).
|
|
|
|
|
|
|
|
const sp_pcontext *p= this;
|
|
|
|
|
|
|
|
while (p && p->m_scope == HANDLER_SCOPE)
|
|
|
|
p= p->m_parent;
|
|
|
|
|
|
|
|
if (!p || !p->m_parent)
|
|
|
|
return NULL;
|
|
|
|
|
2016-10-14 14:52:33 +02:00
|
|
|
return p->m_parent->find_handler(value);
|
2005-04-08 19:58:04 +02:00
|
|
|
}
|
|
|
|
|
2013-06-19 13:32:14 +02:00
|
|
|
|
2017-04-23 18:39:57 +02:00
|
|
|
bool sp_pcontext::add_cursor(const LEX_CSTRING *name, sp_pcontext *param_ctx,
|
MDEV-12011 sql_mode=ORACLE: cursor%ROWTYPE in variable declarations
Implementing cursor%ROWTYPE variables, according to the task description.
This patch includes a refactoring in how sp_instr_cpush and sp_instr_copen
work. This is needed to implement MDEV-10598 later easier, to allow variable
declarations go after cursor declarations (which is currently not allowed).
Before this patch, sp_instr_cpush worked as a Query_arena associated with
the cursor. sp_instr_copen::execute() switched to the sp_instr_cpush's
Query_arena when executing the cursor SELECT statement.
Now the Query_arena associated with the cursor is stored inside an instance
of a new class sp_lex_cursor (a LEX descendand) that contains the cursor SELECT
statement.
This simplifies the implementation, because:
- It's easier to follow the code when everything related to execution
of the cursor SELECT statement is stored inside the same sp_lex_cursor
object (rather than distributed between LEX and sp_instr_cpush).
- It's easier to link an sp_instr_cursor_copy_struct to
sp_lex_cursor rather than to sp_instr_cpush.
- Also, it allows to perform sp_instr_cursor_copy_struct::exec_core()
without having a pointer to sp_instr_cpush, using a pointer to sp_lex_cursor
instead. This will be important for MDEV-10598, because sp_instr_cpush will
happen *after* sp_instr_cursor_copy_struct.
After MDEV-10598 is done, this declaration:
DECLARE
CURSOR cur IS SELECT * FROM t1;
rec cur%ROWTYPE;
BEGIN
OPEN cur;
FETCH cur INTO rec;
CLOSE cur;
END;
will generate about this code:
+-----+--------------------------+
| Pos | Instruction |
+-----+--------------------------+
| 0 | cursor_copy_struct rec@0 | Points to sp_cursor_lex through m_lex_keeper
| 1 | set rec@0 NULL |
| 2 | cpush cur@0 | Points to sp_cursor_lex through m_lex_keeper
| 3 | copen cur@0 | Points to sp_cursor_lex through m_cursor
| 4 | cfetch cur@0 rec@0 |
| 5 | cclose cur@0 |
| 6 | cpop 1 |
+-----+--------------------------+
Notice, "cursor_copy_struct" and "set" will go before "cpush".
Instructions at positions 0, 2, 3 point to the same sp_cursor_lex instance.
2017-03-08 20:20:39 +01:00
|
|
|
sp_lex_cursor *lex)
|
2003-10-10 16:57:21 +02:00
|
|
|
{
|
2013-07-21 16:39:19 +02:00
|
|
|
if (m_cursors.elements() == m_max_cursor_index)
|
2013-06-19 13:32:14 +02:00
|
|
|
++m_max_cursor_index;
|
2003-10-10 16:57:21 +02:00
|
|
|
|
MDEV-12011 sql_mode=ORACLE: cursor%ROWTYPE in variable declarations
Implementing cursor%ROWTYPE variables, according to the task description.
This patch includes a refactoring in how sp_instr_cpush and sp_instr_copen
work. This is needed to implement MDEV-10598 later easier, to allow variable
declarations go after cursor declarations (which is currently not allowed).
Before this patch, sp_instr_cpush worked as a Query_arena associated with
the cursor. sp_instr_copen::execute() switched to the sp_instr_cpush's
Query_arena when executing the cursor SELECT statement.
Now the Query_arena associated with the cursor is stored inside an instance
of a new class sp_lex_cursor (a LEX descendand) that contains the cursor SELECT
statement.
This simplifies the implementation, because:
- It's easier to follow the code when everything related to execution
of the cursor SELECT statement is stored inside the same sp_lex_cursor
object (rather than distributed between LEX and sp_instr_cpush).
- It's easier to link an sp_instr_cursor_copy_struct to
sp_lex_cursor rather than to sp_instr_cpush.
- Also, it allows to perform sp_instr_cursor_copy_struct::exec_core()
without having a pointer to sp_instr_cpush, using a pointer to sp_lex_cursor
instead. This will be important for MDEV-10598, because sp_instr_cpush will
happen *after* sp_instr_cursor_copy_struct.
After MDEV-10598 is done, this declaration:
DECLARE
CURSOR cur IS SELECT * FROM t1;
rec cur%ROWTYPE;
BEGIN
OPEN cur;
FETCH cur INTO rec;
CLOSE cur;
END;
will generate about this code:
+-----+--------------------------+
| Pos | Instruction |
+-----+--------------------------+
| 0 | cursor_copy_struct rec@0 | Points to sp_cursor_lex through m_lex_keeper
| 1 | set rec@0 NULL |
| 2 | cpush cur@0 | Points to sp_cursor_lex through m_lex_keeper
| 3 | copen cur@0 | Points to sp_cursor_lex through m_cursor
| 4 | cfetch cur@0 rec@0 |
| 5 | cclose cur@0 |
| 6 | cpop 1 |
+-----+--------------------------+
Notice, "cursor_copy_struct" and "set" will go before "cpush".
Instructions at positions 0, 2, 3 point to the same sp_cursor_lex instance.
2017-03-08 20:20:39 +01:00
|
|
|
return m_cursors.append(sp_pcursor(name, param_ctx, lex));
|
2003-10-10 16:57:21 +02:00
|
|
|
}
|
|
|
|
|
2013-06-19 13:32:14 +02:00
|
|
|
|
2017-04-23 18:39:57 +02:00
|
|
|
const sp_pcursor *sp_pcontext::find_cursor(const LEX_CSTRING *name,
|
2016-10-21 09:51:49 +02:00
|
|
|
uint *poff,
|
|
|
|
bool current_scope_only) const
|
2003-10-10 16:57:21 +02:00
|
|
|
{
|
2018-02-06 13:55:58 +01:00
|
|
|
uint i= (uint)m_cursors.elements();
|
Various bug fixes:
- Duplicate parameters/variables, conditions and cursors (not allowed).
- ITERATE in labelled BEGIN-END (not allowed).
- Missing SQLSTATE [VALUE] keywords in CONDITION/HANDLER declaration (added).
- Empty BEGIN-END (now allowed).
- End label (now optional).
include/mysqld_error.h:
New error code for duplicate things (vars et al) in SPs.
mysql-test/r/sp-error.result:
New error tests for ITERATE in begin-end block and duplicate variables,
conditions and cursors.
mysql-test/r/sp.result:
New tests for empty begin-end blocks, overriding local variables outside scope
only, leave a begin-end block, and SQLSTATE [VALUE] words for CONDITION/HANDLER
declarations.
mysql-test/t/sp-error.test:
New error tests for ITERATE in begin-end block and duplicate variables,
conditions and cursors.
mysql-test/t/sp.test:
New tests for empty begin-end blocks, overriding local variables outside scope
only, leave a begin-end block, and SQLSTATE [VALUE] words for CONDITION/HANDLER
declarations.
sql/lex.h:
New SQLSTATE keyword.
sql/share/czech/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/danish/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/dutch/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/english/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/estonian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/french/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/german/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/greek/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/hungarian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/italian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/japanese/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/korean/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/norwegian-ny/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/norwegian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/polish/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/portuguese/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/romanian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/russian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/serbian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/slovak/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/spanish/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/swedish/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/share/ukrainian/errmsg.txt:
New error message for duplicate things (vars et al) in SPs.
sql/sp_pcontext.cc:
Keep track on scope limits for error checking of duplicate variables,
conditions and cursors.
sql/sp_pcontext.h:
Keep track on scope limits for error checking of duplicate variables,
conditions and cursors.
Also need to flag BEGIN labels to check for illegal ITERATEs.
sql/sql_yacc.yy:
End-labels in SPs loop and begin-end blocks are now optional.
SQLSTATE [VALUE] added to syntax for sqlstates.
Check for duplicate variable, condition and cursor declarations, but
only in the same scope.
Empty BEGIN-END statements now allowed.
Check if ITERATE is referring to a BEGIN label.
2003-11-13 19:34:56 +01:00
|
|
|
|
2004-08-26 12:54:30 +02:00
|
|
|
while (i--)
|
2003-10-10 16:57:21 +02:00
|
|
|
{
|
2017-04-23 18:39:57 +02:00
|
|
|
LEX_CSTRING n= m_cursors.at(i);
|
2003-10-10 16:57:21 +02:00
|
|
|
|
2020-01-26 17:27:13 +01:00
|
|
|
if (system_charset_info->strnncoll(name->str, name->length,
|
|
|
|
n.str, n.length) == 0)
|
2003-10-10 16:57:21 +02:00
|
|
|
{
|
2006-04-07 16:53:15 +02:00
|
|
|
*poff= m_cursor_offset + i;
|
2016-10-21 09:51:49 +02:00
|
|
|
return &m_cursors.at(i);
|
2003-10-10 16:57:21 +02:00
|
|
|
}
|
|
|
|
}
|
2013-06-19 13:32:14 +02:00
|
|
|
|
|
|
|
return (!current_scope_only && m_parent) ?
|
|
|
|
m_parent->find_cursor(name, poff, false) :
|
2016-10-21 09:51:49 +02:00
|
|
|
NULL;
|
2003-10-10 16:57:21 +02:00
|
|
|
}
|
Background:
Since long, the compiled code of stored routines has been printed in the trace file
when starting mysqld with the "--debug" flag. (At creation time only, and only in
debug builds of course.) This has been helpful when debugging stored procedure
execution, but it's a bit awkward to use. Also, the printing of some of the
instructions is a bit terse, in particular for sp_instr_stmt where only the command
code was printed.
This improves the printout of several of the instructions, and adds the debugging-
only commands "show procedure code <name>" and "show function code <name>".
(In non-debug builds they are not available.)
sql/lex.h:
New symbol for debug-only command (e.g. show procedure code).
sql/sp_head.cc:
Fixed some minor debug-mode bugs in show_create_*().
New method for debugging: sp_head::show_routine_code() - returns the "assembly code"
for a stored routine as a result set.
Improved the print() methods for many sp_instr* classes, particularly for
sp_instr_stmt where the query string is printed as well (up to a max length, just
to give a hint of which statement it is). Also print the names of variables and
cursors in some instruction.
sql/sp_head.h:
New debugging-only method in sp_head: show_routine_code().
Added offset member to sp_instr_cpush for improved debug printing.
sql/sp_pcontext.cc:
Moved find_pvar(uint i) method from sp_pcontext.h, and made it work for all
frames, not just the first one. (For debugging purposes)
Added a similar find_cursor(uint i, ...) method, for debugging.
sql/sp_pcontext.h:
Moved find_pvar(uint i) method to sp_pcontext.cc.
Added a similar find_cursor(uint i, ...) method, for debugging.
sql/sql_lex.h:
Added new sql_command codes for debugging.
sql/sql_parse.cc:
Added new commands for debugging, e.g. "show procedure code".
sql/sql_yacc.yy:
Added new commands for debugging purposes:
"show procedure code ..." and "show function code ...".
These are only enabled in debug builds, otherwise they result in a syntax error.
(I.e. they don't exist)
2005-11-17 11:11:48 +01:00
|
|
|
|
2005-12-07 15:01:17 +01:00
|
|
|
|
2013-06-19 13:32:14 +02:00
|
|
|
void sp_pcontext::retrieve_field_definitions(
|
2016-12-06 06:05:52 +01:00
|
|
|
List<Spvar_definition> *field_def_lst) const
|
2005-12-07 15:01:17 +01:00
|
|
|
{
|
|
|
|
/* Put local/context fields in the result list. */
|
|
|
|
|
MDEV-12441 Variables declared after cursors with parameters lose values
Parse context frames (sp_pcontext) can have holes in variable run-time offsets,
the missing offsets reside on the children contexts in such cases.
Example:
CREATE PROCEDURE p1() AS
x0 INT:=100; -- context 0, position 0, run-time 0
CURSOR cur(
p0 INT, -- context 1, position 0, run-time 1
p1 INT -- context 1, position 1, run-time 2
) IS SELECT p0, p1;
x1 INT:=101; -- context 0, position 1, run-time 3
BEGIN
...
END;
Fixing a few methods to take this into account:
- sp_pcontext::find_variable()
- sp_pcontext::retrieve_field_definitions()
- LEX::sp_variable_declarations_init()
- LEX::sp_variable_declarations_finalize()
- LEX::sp_variable_declarations_rowtype_finalize()
- LEX::sp_variable_declarations_with_ref_finalize()
Adding a convenience method:
sp_pcontext::get_last_context_variable(uint offset_from_the_end);
to access variables from the end, rather than from the beginning.
This helps to loop through the context variable array (m_vars)
on the fragment that does not have any holes.
Additionally, renaming sp_pcontext::find_context_variable() to
sp_pcontext::get_context_variable(). This method simply returns
the variable by its index. So let's rename to avoid assumptions
that some heavy lookup is going on inside.
2017-04-05 08:52:31 +02:00
|
|
|
size_t next_child= 0;
|
2013-07-21 16:39:19 +02:00
|
|
|
for (size_t i= 0; i < m_vars.elements(); ++i)
|
2005-12-07 15:01:17 +01:00
|
|
|
{
|
2013-06-19 13:32:14 +02:00
|
|
|
sp_variable *var_def= m_vars.at(i);
|
2005-12-07 15:01:17 +01:00
|
|
|
|
MDEV-12441 Variables declared after cursors with parameters lose values
Parse context frames (sp_pcontext) can have holes in variable run-time offsets,
the missing offsets reside on the children contexts in such cases.
Example:
CREATE PROCEDURE p1() AS
x0 INT:=100; -- context 0, position 0, run-time 0
CURSOR cur(
p0 INT, -- context 1, position 0, run-time 1
p1 INT -- context 1, position 1, run-time 2
) IS SELECT p0, p1;
x1 INT:=101; -- context 0, position 1, run-time 3
BEGIN
...
END;
Fixing a few methods to take this into account:
- sp_pcontext::find_variable()
- sp_pcontext::retrieve_field_definitions()
- LEX::sp_variable_declarations_init()
- LEX::sp_variable_declarations_finalize()
- LEX::sp_variable_declarations_rowtype_finalize()
- LEX::sp_variable_declarations_with_ref_finalize()
Adding a convenience method:
sp_pcontext::get_last_context_variable(uint offset_from_the_end);
to access variables from the end, rather than from the beginning.
This helps to loop through the context variable array (m_vars)
on the fragment that does not have any holes.
Additionally, renaming sp_pcontext::find_context_variable() to
sp_pcontext::get_context_variable(). This method simply returns
the variable by its index. So let's rename to avoid assumptions
that some heavy lookup is going on inside.
2017-04-05 08:52:31 +02:00
|
|
|
/*
|
|
|
|
The context can have holes in run-time offsets,
|
|
|
|
the missing offsets reside on the children contexts in such cases.
|
|
|
|
Example:
|
|
|
|
CREATE PROCEDURE p1() AS
|
|
|
|
x0 INT:=100; -- context 0, position 0, run-time 0
|
|
|
|
CURSOR cur(
|
|
|
|
p0 INT, -- context 1, position 0, run-time 1
|
|
|
|
p1 INT -- context 1, position 1, run-time 2
|
|
|
|
) IS SELECT p0, p1;
|
|
|
|
x1 INT:=101; -- context 0, position 1, run-time 3
|
|
|
|
BEGIN
|
|
|
|
...
|
|
|
|
END;
|
|
|
|
See more comments in sp_pcontext::find_variable().
|
|
|
|
We must retrieve the definitions in the order of their run-time offsets.
|
|
|
|
Check that there are children that should go before the current variable.
|
|
|
|
*/
|
|
|
|
for ( ; next_child < m_children.elements(); next_child++)
|
|
|
|
{
|
|
|
|
sp_pcontext *child= m_children.at(next_child);
|
|
|
|
if (!child->context_var_count() ||
|
|
|
|
child->get_context_variable(0)->offset > var_def->offset)
|
|
|
|
break;
|
|
|
|
/*
|
|
|
|
All variables on the embedded context (that fills holes of the parent)
|
|
|
|
should have the run-time offset strictly less than var_def.
|
|
|
|
*/
|
|
|
|
DBUG_ASSERT(child->get_context_variable(0)->offset < var_def->offset);
|
|
|
|
DBUG_ASSERT(child->get_last_context_variable()->offset < var_def->offset);
|
|
|
|
child->retrieve_field_definitions(field_def_lst);
|
|
|
|
}
|
2005-12-07 15:01:17 +01:00
|
|
|
field_def_lst->push_back(&var_def->field_def);
|
|
|
|
}
|
|
|
|
|
MDEV-12441 Variables declared after cursors with parameters lose values
Parse context frames (sp_pcontext) can have holes in variable run-time offsets,
the missing offsets reside on the children contexts in such cases.
Example:
CREATE PROCEDURE p1() AS
x0 INT:=100; -- context 0, position 0, run-time 0
CURSOR cur(
p0 INT, -- context 1, position 0, run-time 1
p1 INT -- context 1, position 1, run-time 2
) IS SELECT p0, p1;
x1 INT:=101; -- context 0, position 1, run-time 3
BEGIN
...
END;
Fixing a few methods to take this into account:
- sp_pcontext::find_variable()
- sp_pcontext::retrieve_field_definitions()
- LEX::sp_variable_declarations_init()
- LEX::sp_variable_declarations_finalize()
- LEX::sp_variable_declarations_rowtype_finalize()
- LEX::sp_variable_declarations_with_ref_finalize()
Adding a convenience method:
sp_pcontext::get_last_context_variable(uint offset_from_the_end);
to access variables from the end, rather than from the beginning.
This helps to loop through the context variable array (m_vars)
on the fragment that does not have any holes.
Additionally, renaming sp_pcontext::find_context_variable() to
sp_pcontext::get_context_variable(). This method simply returns
the variable by its index. So let's rename to avoid assumptions
that some heavy lookup is going on inside.
2017-04-05 08:52:31 +02:00
|
|
|
/* Put the fields of the remaining enclosed contexts in the result list. */
|
2005-12-07 15:01:17 +01:00
|
|
|
|
MDEV-12441 Variables declared after cursors with parameters lose values
Parse context frames (sp_pcontext) can have holes in variable run-time offsets,
the missing offsets reside on the children contexts in such cases.
Example:
CREATE PROCEDURE p1() AS
x0 INT:=100; -- context 0, position 0, run-time 0
CURSOR cur(
p0 INT, -- context 1, position 0, run-time 1
p1 INT -- context 1, position 1, run-time 2
) IS SELECT p0, p1;
x1 INT:=101; -- context 0, position 1, run-time 3
BEGIN
...
END;
Fixing a few methods to take this into account:
- sp_pcontext::find_variable()
- sp_pcontext::retrieve_field_definitions()
- LEX::sp_variable_declarations_init()
- LEX::sp_variable_declarations_finalize()
- LEX::sp_variable_declarations_rowtype_finalize()
- LEX::sp_variable_declarations_with_ref_finalize()
Adding a convenience method:
sp_pcontext::get_last_context_variable(uint offset_from_the_end);
to access variables from the end, rather than from the beginning.
This helps to loop through the context variable array (m_vars)
on the fragment that does not have any holes.
Additionally, renaming sp_pcontext::find_context_variable() to
sp_pcontext::get_context_variable(). This method simply returns
the variable by its index. So let's rename to avoid assumptions
that some heavy lookup is going on inside.
2017-04-05 08:52:31 +02:00
|
|
|
for (size_t i= next_child; i < m_children.elements(); ++i)
|
2013-06-19 13:32:14 +02:00
|
|
|
m_children.at(i)->retrieve_field_definitions(field_def_lst);
|
2005-12-07 15:01:17 +01:00
|
|
|
}
|
|
|
|
|
2013-06-19 13:32:14 +02:00
|
|
|
|
2016-10-21 09:51:49 +02:00
|
|
|
const sp_pcursor *sp_pcontext::find_cursor(uint offset) const
|
Background:
Since long, the compiled code of stored routines has been printed in the trace file
when starting mysqld with the "--debug" flag. (At creation time only, and only in
debug builds of course.) This has been helpful when debugging stored procedure
execution, but it's a bit awkward to use. Also, the printing of some of the
instructions is a bit terse, in particular for sp_instr_stmt where only the command
code was printed.
This improves the printout of several of the instructions, and adds the debugging-
only commands "show procedure code <name>" and "show function code <name>".
(In non-debug builds they are not available.)
sql/lex.h:
New symbol for debug-only command (e.g. show procedure code).
sql/sp_head.cc:
Fixed some minor debug-mode bugs in show_create_*().
New method for debugging: sp_head::show_routine_code() - returns the "assembly code"
for a stored routine as a result set.
Improved the print() methods for many sp_instr* classes, particularly for
sp_instr_stmt where the query string is printed as well (up to a max length, just
to give a hint of which statement it is). Also print the names of variables and
cursors in some instruction.
sql/sp_head.h:
New debugging-only method in sp_head: show_routine_code().
Added offset member to sp_instr_cpush for improved debug printing.
sql/sp_pcontext.cc:
Moved find_pvar(uint i) method from sp_pcontext.h, and made it work for all
frames, not just the first one. (For debugging purposes)
Added a similar find_cursor(uint i, ...) method, for debugging.
sql/sp_pcontext.h:
Moved find_pvar(uint i) method to sp_pcontext.cc.
Added a similar find_cursor(uint i, ...) method, for debugging.
sql/sql_lex.h:
Added new sql_command codes for debugging.
sql/sql_parse.cc:
Added new commands for debugging, e.g. "show procedure code".
sql/sql_yacc.yy:
Added new commands for debugging purposes:
"show procedure code ..." and "show function code ...".
These are only enabled in debug builds, otherwise they result in a syntax error.
(I.e. they don't exist)
2005-11-17 11:11:48 +01:00
|
|
|
{
|
2006-04-07 16:53:15 +02:00
|
|
|
if (m_cursor_offset <= offset &&
|
2013-06-19 13:32:14 +02:00
|
|
|
offset < m_cursor_offset + m_cursors.elements())
|
|
|
|
{
|
|
|
|
return &m_cursors.at(offset - m_cursor_offset); // This frame
|
Background:
Since long, the compiled code of stored routines has been printed in the trace file
when starting mysqld with the "--debug" flag. (At creation time only, and only in
debug builds of course.) This has been helpful when debugging stored procedure
execution, but it's a bit awkward to use. Also, the printing of some of the
instructions is a bit terse, in particular for sp_instr_stmt where only the command
code was printed.
This improves the printout of several of the instructions, and adds the debugging-
only commands "show procedure code <name>" and "show function code <name>".
(In non-debug builds they are not available.)
sql/lex.h:
New symbol for debug-only command (e.g. show procedure code).
sql/sp_head.cc:
Fixed some minor debug-mode bugs in show_create_*().
New method for debugging: sp_head::show_routine_code() - returns the "assembly code"
for a stored routine as a result set.
Improved the print() methods for many sp_instr* classes, particularly for
sp_instr_stmt where the query string is printed as well (up to a max length, just
to give a hint of which statement it is). Also print the names of variables and
cursors in some instruction.
sql/sp_head.h:
New debugging-only method in sp_head: show_routine_code().
Added offset member to sp_instr_cpush for improved debug printing.
sql/sp_pcontext.cc:
Moved find_pvar(uint i) method from sp_pcontext.h, and made it work for all
frames, not just the first one. (For debugging purposes)
Added a similar find_cursor(uint i, ...) method, for debugging.
sql/sp_pcontext.h:
Moved find_pvar(uint i) method to sp_pcontext.cc.
Added a similar find_cursor(uint i, ...) method, for debugging.
sql/sql_lex.h:
Added new sql_command codes for debugging.
sql/sql_parse.cc:
Added new commands for debugging, e.g. "show procedure code".
sql/sql_yacc.yy:
Added new commands for debugging purposes:
"show procedure code ..." and "show function code ...".
These are only enabled in debug builds, otherwise they result in a syntax error.
(I.e. they don't exist)
2005-11-17 11:11:48 +01:00
|
|
|
}
|
2013-06-19 13:32:14 +02:00
|
|
|
|
|
|
|
return m_parent ?
|
|
|
|
m_parent->find_cursor(offset) : // Some previous frame
|
|
|
|
NULL; // Index out of bounds
|
Background:
Since long, the compiled code of stored routines has been printed in the trace file
when starting mysqld with the "--debug" flag. (At creation time only, and only in
debug builds of course.) This has been helpful when debugging stored procedure
execution, but it's a bit awkward to use. Also, the printing of some of the
instructions is a bit terse, in particular for sp_instr_stmt where only the command
code was printed.
This improves the printout of several of the instructions, and adds the debugging-
only commands "show procedure code <name>" and "show function code <name>".
(In non-debug builds they are not available.)
sql/lex.h:
New symbol for debug-only command (e.g. show procedure code).
sql/sp_head.cc:
Fixed some minor debug-mode bugs in show_create_*().
New method for debugging: sp_head::show_routine_code() - returns the "assembly code"
for a stored routine as a result set.
Improved the print() methods for many sp_instr* classes, particularly for
sp_instr_stmt where the query string is printed as well (up to a max length, just
to give a hint of which statement it is). Also print the names of variables and
cursors in some instruction.
sql/sp_head.h:
New debugging-only method in sp_head: show_routine_code().
Added offset member to sp_instr_cpush for improved debug printing.
sql/sp_pcontext.cc:
Moved find_pvar(uint i) method from sp_pcontext.h, and made it work for all
frames, not just the first one. (For debugging purposes)
Added a similar find_cursor(uint i, ...) method, for debugging.
sql/sp_pcontext.h:
Moved find_pvar(uint i) method to sp_pcontext.cc.
Added a similar find_cursor(uint i, ...) method, for debugging.
sql/sql_lex.h:
Added new sql_command codes for debugging.
sql/sql_parse.cc:
Added new commands for debugging, e.g. "show procedure code".
sql/sql_yacc.yy:
Added new commands for debugging purposes:
"show procedure code ..." and "show function code ...".
These are only enabled in debug builds, otherwise they result in a syntax error.
(I.e. they don't exist)
2005-11-17 11:11:48 +01:00
|
|
|
}
|
2017-02-02 19:59:07 +01:00
|
|
|
|
|
|
|
|
2017-03-10 11:11:07 +01:00
|
|
|
bool sp_pcursor::check_param_count_with_error(uint param_count) const
|
|
|
|
{
|
|
|
|
if (param_count != (m_param_context ?
|
|
|
|
m_param_context->context_var_count() : 0))
|
|
|
|
{
|
2017-04-23 18:39:57 +02:00
|
|
|
my_error(ER_WRONG_PARAMCOUNT_TO_CURSOR, MYF(0), LEX_CSTRING::str);
|
2017-03-10 11:11:07 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-02 19:59:07 +01:00
|
|
|
const Spvar_definition *
|
2017-04-23 18:39:57 +02:00
|
|
|
sp_variable::find_row_field(const LEX_CSTRING *var_name,
|
|
|
|
const LEX_CSTRING *field_name,
|
2017-02-02 19:59:07 +01:00
|
|
|
uint *row_field_offset)
|
|
|
|
{
|
|
|
|
if (!field_def.is_row())
|
|
|
|
{
|
|
|
|
my_printf_error(ER_UNKNOWN_ERROR,
|
2017-04-23 18:39:57 +02:00
|
|
|
"'%s' is not a row variable", MYF(0), var_name->str);
|
2017-02-02 19:59:07 +01:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
const Spvar_definition *def;
|
2017-04-23 18:39:57 +02:00
|
|
|
if ((def= field_def.find_row_field_by_name(field_name, row_field_offset)))
|
2017-02-02 19:59:07 +01:00
|
|
|
return def;
|
2017-03-03 12:02:08 +01:00
|
|
|
my_error(ER_ROW_VARIABLE_DOES_NOT_HAVE_FIELD, MYF(0),
|
2017-04-23 18:39:57 +02:00
|
|
|
var_name->str, field_name->str);
|
2017-02-02 19:59:07 +01:00
|
|
|
return NULL;
|
|
|
|
}
|