学习mysql存储过程执行解析过程,执行一下存储过程
create procedure aa()
begin
declare x varchar(10);
select count(*) from test where aaa = x ;
end
在JOIN::exec上设个断点,跟踪一下
执行堆栈如下:
#0 JOIN::exec (this=0x900e548) at sql_select.cc:2311
#1 0x08268373 in mysql_select (thd=0xb53d2fd0, rref_pointer_array=0x9005984, tables=0x9006040, wild_num=0, fields=@0x9005914, conds=0x90065f8, og_num=0, order=0x0, group=0x0, having=0x0, proc_param=0x0, select_options=2147765760, result=0x900c698, unit=0x90055ec, select_lex=0x9005880) at sql_select.cc:3067
#2 0x0826887d in handle_select (thd=0xb53d2fd0, lex=0x9005590, result=0x900c698, setup_tables_done_option=0) at sql_select.cc:310
#3 0x081e1af7 in execute_sqlcom_select (thd=0xb53d2fd0, all_tables=0x9006040) at sql_parse.cc:4943
#4 0x081e432f in mysql_execute_command (thd=0xb53d2fd0) at sql_parse.cc:2157
#5 0x0835c987 in sp_instr_stmt::exec_core (this=0x90066f0, thd=0xb53d2fd0, nextp=0xb54912d0) at sp_head.cc:2927
#6 0x0835cbd1 in sp_lex_keeper::reset_lex_and_exec_core (this=0x9006718, thd=0xb53d2fd0, nextp=0xb54912d0, open_tables=false, instr=0x90066f0) at sp_head.cc:2751
#7 0x08363962 in sp_instr_stmt::execute (this=0x90066f0, thd=0xb53d2fd0, nextp=0xb54912d0) at sp_head.cc:2864
#8 0x08360f89 in sp_head::execute (this=0x9004560, thd=0xb53d2fd0) at sp_head.cc:1248
#9 0x08361a53 in sp_head::execute_procedure (this=0x9004560, thd=0xb53d2fd0, args=0xb53d44bc) at sp_head.cc:1989
#10 0x081e966a in mysql_execute_command (thd=0xb53d2fd0) at sql_parse.cc:4401
#11 0x081ebbfa in mysql_parse (thd=0xb53d2fd0, inBuf=0x8fdfa58 "call aa()", length=9, found_semicolon=0xb5491f14) at sql_parse.cc:5958
#12 0x081ecae6 in dispatch_command (command=COM_QUERY, thd=0xb53d2fd0, packet=0xb53f35c9 "call aa()", packet_length=9) at sql_parse.cc:1049
#13 0x081eddaa in do_command (thd=0xb53d2fd0) at sql_parse.cc:731
#14 0x081dd5a7 in handle_one_connection (arg=0xb53d2fd0) at sql_connect.cc:1146
#15 0x4dfe92db in start_thread (arg=0xb5492790) at pthread_create.c:296
#16 0x006cf14e in clone () from /lib/libc.so.
具体代码
在sql_parse.cc中
case SQLCOM_CALL:
....
sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname,
&thd->sp_proc_cache, TRUE)) -------此处对存储过程进行解析
....
res= sp->execute_procedure(thd, &lex->value_list); -------执行存储过程
}
bool sp_head::execute_procedure(THD *thd, List<Item> *args){
....
//前面对参数进行一些处理
if (!err_status)
err_status= execute(thd);//具体执行存储过程
...对出参进行处理
}
bool sp_head::execute(THD *thd){
...
do
{
sp_instr *i;
uint hip;
i = get_instr(ip);// Returns NULL when we're done.
err_status= i->execute(thd, &ip); //执行存储过程中的每一个语句,每个具体语句都解析为sp_instr的子类
}while (!err_status && !thd->killed && !thd->is_fatal_error);
//上面循环其实就是一个sql的执行引擎,不断读入执行,直到结束
}
int sp_instr_stmt::exec_core(THD *thd, uint *nextp)
{
MYSQL_QUERY_EXEC_START(thd->query,
thd->thread_id,
(char *) (thd->db ? thd->db: ""),
thd->security_ctx->priv_user,
(char *) thd->security_ctx->host_or_ip,
3);
int res= mysql_execute_command(thd); //对每一个sql进行执行。这里就和普通的sql是一样了
MYSQL_QUERY_EXEC_DONE(res);
*nextp= m_ip+1; //将上面ip推进到下一条语句,让上面的循环执行下一个语句
return res;
}
看一下解析器解析的中where
where aaa = x
|
|--> where Item_func_eq -----表示这是个等于条件操作
| / Item_field ----代表字段aaa
|-----> Item** args -----|
\ Item_sp_local--代表变量x
解析在sql_yacc.yy中
simple_ident:
ident
{
THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= YYLIP;
sp_variable_t *spv;
sp_pcontext *spc = lex->spcont;
if (spc && (spv = spc->find_variable(&$1))) //判断语句中是否有变量
{
/* We're compiling a stored procedure and found a variable */
if (! lex->parsing_options.allows_variable)
{
my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
MYSQL_YYABORT;
}
Item_splocal *splocal;
splocal= new (thd->mem_root)
Item_splocal($1,
spv->offset, spv->type,
lip->get_tok_start_prev() - lex->sphead->m_tmp_query,
lip->get_tok_end() - lip->get_tok_start_prev());
if (splocal == NULL)
MYSQL_YYABORT;
#ifndef DBUG_OFF
splocal->m_sp= lex->sphead;
#endif
$$= splocal;
lex->safe_to_cache_query=0;
}
else
{
SELECT_LEX *sel= Select;
if ((sel->parsing_place != IN_HAVING) ||
(sel->get_in_sum_expr() > 0))
{
$$= new (thd->mem_root) Item_field(Lex->current_context(),
NullS, NullS, $1.str);
}
else
{
$$= new (thd->mem_root) Item_ref(Lex->current_context(),
NullS, NullS, $1.str);
}
if ($$ == NULL)
MYSQL_YYABORT;
}
}
| simple_ident_q { $$= $1; }
;
相关推荐
MySQL存储过程是数据库管理系统中的一种重要功能,它允许开发者编写一系列复杂的SQL语句,并作为一个单元进行执行,提高代码复用性和效率。然而,与普通的编程语言一样,存储过程的调试同样至关重要,因为错误的存储...
MySQL存储过程 MySQL存储过程(Stored Procedure)...这些信息可以用来帮助开发者跟踪过程的变化和维护过程的历史记录。 MySQL存储过程是一种强大的数据库对象,可以帮助开发者提高数据库的性能、安全性和可维护性。
MySQL存储过程是数据库管理系统中的一种重要功能,它允许程序员或数据库管理员预编译一系列SQL语句,形成一个可重用的程序单元。在本场景中,我们关注的是如何利用存储过程进行数据库的备份与还原,这在数据管理中至...
- **审计日志**:许多数据库系统如MySQL、SQL Server提供内置的审计功能,可以开启存储过程执行的审计,但可能需要额外的存储空间和处理开销。 - **动态SQL**:在存储过程中,使用动态SQL来记录调用信息,比如插入...
9. **存储过程的调试**:MySQL 5.0提供了更好的调试工具,允许开发者检查存储过程的执行步骤,查找并修复错误。 10. **嵌套存储过程**:MySQL 5.0允许在一个存储过程中调用另一个存储过程,实现更复杂的逻辑结构。 ...
它也可能有调试功能,如设置断点、查看变量值、跟踪执行步骤等,这对于复杂存储过程的开发和维护至关重要。 5. **使用场景**: - 在数据库设计阶段,存储过程助手能帮助创建和测试过程逻辑。 - 在开发阶段,它...
在MySQL数据库中,存储过程是一组为了完成特定功能的SQL语句集,可以视为数据库中的可执行程序。它们允许开发者将多次使用的代码封装起来,提高代码复用性,降低数据库交互的复杂性。然而,随着存储过程数量的增长和...
5. **版本控制**:集成版本控制系统,便于跟踪和管理存储过程的变更历史。 6. **数据库兼容性**:适应多种数据库系统,如MySQL、Oracle、SQL Server等,提供跨平台的支持。 例如,"存储过程生成工具.msi"可能是一个...
MySQL存储过程的权限问题涉及到数据库管理系统中的访问控制和安全策略。在MySQL中,存储过程是一种预编译的SQL代码集合,允许开发者封装复杂的业务逻辑,提高数据库操作的效率和安全性。然而,不当的权限配置可能...
MySQL存储过程异常处理是数据库开发中的重要组成部分,它允许开发者在遇到错误时进行优雅的控制流程,而不是让程序中断。在存储过程中,异常处理通常涉及捕获错误、记录错误信息,甚至在某些情况下,继续执行后续的...
大多数数据库管理系统提供了调试工具,如SQL Server的SSMS中的“存储过程调试器”,帮助开发者跟踪存储过程的执行流程,检查变量值,定位并修复错误。 优化存储过程是提升数据库性能的关键。这包括合理设计参数,...
5. **日志记录**:为了跟踪和审计短信发送情况,通常会在存储过程中添加日志记录,保存发送时间、发送状态、接收方号码等信息。 6. **安全考虑**:确保敏感信息,如API密钥,不会直接暴露在存储过程中。一种常见...
综上所述,这个基于Servlet和MySQL存储过程的进销存系统,结合了Java Web的强大处理能力和数据库的高效存储,为企业的库存管理提供了稳定且高效的解决方案。通过对各个模块的精细设计和优化,能够有效地提升企业的...
6. **错误处理与日志**:在执行过程中,Ansible会记录输出,包括成功和失败的信息。根据需要,你可以配置日志记录以跟踪任务执行情况。 7. **安全考虑**:在实际环境中,避免在Playbook中明文写入数据库用户名和...
编写存储过程和函数通常涉及SQL语法,例如在MySQL中,我们可以这样创建一个简单的存储过程: ```sql CREATE PROCEDURE `myProcedure`(IN param1 INT, OUT param2 VARCHAR(50)) BEGIN SELECT 'Hello, ' AS `msg`, ...
《MySQL存储过程调试工具——Debugger for MySQL深度解析》 在数据库管理领域,MySQL因其高效、稳定及开源等特性,被广泛应用于各种业务场景。然而,随着应用复杂度的提升,开发和维护存储过程的需求日益凸显,这就...
6. **版本管理**:对比不同版本的存储过程,方便跟踪和管理代码变更。 7. **兼容性**:支持多种数据库管理系统,如MySQL、SQL Server、Oracle等。 在使用"超级SQL存储过程解密器 V3.0.exe"时,用户需要注意以下几点...
在存储过程中,声明了多个变量,如`v_exit`, `v_spid`, `v_id`, `i`, `c_table`等,它们分别用于处理流程控制、记录SPID(服务器进程ID)、跟踪循环计数、选择目标表等。变量`v_UniqueKey`, `v_TagCatalogId`, `v_...