在mysql中添加新源文件,以及 如何…

来源:互联网 发布:父亲写的散文诗 知乎 编辑:程序博客网 时间:2024/05/08 12:05

本文主要介绍如何在mysql 中添加新的源文件以及如何在客户端打印列表信息。这两个内容没有必然的联系,这里放在一起介绍主要是因为这两个功能我是一起尝试的。

 

1.添加新源文件

mysql5.5的编译是基于cmake来进行的,所以当添加新的源文件的时候,需要在对应源码目录的cmake配置文件CMakeList.txt中添加新源文件的信息。

本例中添加的新文件是gaoshow.h 和gaoshow.cc, 它们都在sql源码目录下。

编辑sql源码目录下的CMakeList.txt,大约第39行处找到变量定义 “SET(SQL_SHARED_SOURCES”在其后的列表的末尾添加gaoshow.cc (cmake中只需要添加.cc文件,不需要添加.h头文件)。

 

2.添加“客户端打印列表信息”的功能

这个功能基于之前的博文《如何在修改mysql代码添加新命令》:http://hi.baidu.com/gao1738/blog/item/716e1aeb3e0a5a0b6c22eb46.html。

在《如何在修改mysql代码添加新命令》中我添加了一条新的命令"DISPATCH ADD",现在在该命令的命令处理代码处:

sql_parse.cc中的 “mysql_execute_command”函数中的“caseSQLCOM_DISPATCH_ADD:”。具体修改后的处理代码如下:

if (!strcmp(lex->dispatch_message,"gao"))
     
      global_system_variables.node_type=1;
      show_dispatch_info(thd,lex->dispatch_message);
      //my_ok(thd);
      my_eof(thd);                             //注:这里一定要用
my_eof(thd)来结束,而不能用my_ok(thd),否则执行该命令的过程中

                                                         // mysql会卡死在哪

                                                        // 但如果这条命令没有向客户端发送数据的话  就用my_ok(thd)

                                                         // 具体的解释可以查看sql/sql_class.cc的3111行。当服务端发送数据的metadata到客户端之后

                                                         // 客户端总是期待服务端发送的数据集以 "eof" 或 “error packet”结尾。

     

show_dispatch_info” 函数定义在新填的源文件中:

这个头文件需要在sql_parse.cc中被include

#ifndef GAO_SHOW
#define GAO_SHOW
bool show_dispatch_info(THD *thd, char *message);
#endif

#include "sql_parse.h"
#include "gaoshow.h"
#include <my_dir.h>

bool show_dispatch_info(THD *thd, char *message)
{
  Protocol *protocol=thd->protocol;
  DBUG_ENTER("show_dispatch_info");

 List<Item> field_list;

  field_list.push_back(newItem_empty_string("message",255));   //注:这里是设置表头
  field_list.push_back(newItem_return_int("num",20,MYSQL_TYPE_LONGLONG));
//注:这里是设置表头
  if(protocol->send_result_set_metadata(&field_list,
                                        Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
   DBUG_RETURN(TRUE);
 protocol->prepare_for_resend();
 protocol->store(message,&my_charset_bin);  
//注:这里是设置表头对应的值,按顺序一一对应
 protocol->store((ulonglong)10);                        //注:这里是设置表头对应的值,按顺序一一对应
  if(protocol->write())
   DBUG_RETURN(TRUE);
  else
   DBUG_RETURN(FALSE);

}

 

3. 测试:

这里我们直接使用《如何在修改mysql代码添加新命令》中定义的测试用例, 执行结果如下:

==============================================================================

TEST                                     RESULT   TIME (ms) orCOMMENT
--------------------------------------------------------------------------

worker[1] Using MTR_BUILD_THREAD 300, with reserved ports13000..13009
DISPATCH ADD gao;
message   num
gao    10
show variables like 'node_type';
Variable_name   Value
node_type   1
main.gao                                [ pass]     1
 

4.打印多行数据

打印多行的过程和打印一行很类似, 也是通过protocol对象, 也是先设置并发送数据的metadata,然后一行一行发送,发送具体一行的代码可以参考sql/sql_class.cc中1895行的send_data函数。下面是一个简单的实例:

bool show_dispatch_info(THD *thd, const char *message)
{
  Protocol *protocol=thd->protocol; 
  DBUG_ENTER("show_dispatch_info");
  List<Item>field_list;             //用这个list存放metadata
  field_list.push_back(newItem_empty_string("message",255));                              //这里是设置metadata
  field_list.push_back(newItem_return_int("Position",20,MYSQL_TYPE_LONGLONG));//这里是设置metadata
  if(protocol->send_result_set_metadata(&field_list,                                                       //向客户端发送要显示的metadata
                                        Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
   DBUG_RETURN(TRUE);

  List<Item>items;                                          //这个list用来存放每一行的数据

  items.push_back(new Item_string(message,strlen(message),system_charset_info));  //放第一个数据项

                                                                //注这里的message中的值如果你不是在这个命令使用,而是要保存到以后的命令中使用,

                                                            //那么需要把它深拷贝到另一块new的内存中。 因为lex中的对象在这条语句结束后就释放了。

  items.push_back(newItem_int(10));                                             //放第二个数据项
  send_row_data(items, protocol,thd);                             //这个函数在下面定义了
 items.delete_elements();                                               //清空以发送的数据,以便存下一条数据
  items.push_back(new Item_string("end",strlen("end"), system_charset_info));
  items.push_back(new Item_int(0));
  send_row_data(items, protocol, thd);
  items.delete_elements();
  items.push_back(new Item_string("end",strlen("end"), system_charset_info));
  items.push_back(new Item_int(0));
  send_row_data(items, protocol, thd);
  DBUG_RETURN(TRUE);
}

bool send_row_data(List<Item> l,Protocol *p, THD *thd)
{

 DBUG_ENTER("show_row_data");               //对于每个函数这个必须放在第一行,它告诉debuger进入了一个新的用户函数,并且在栈中

                                                                       //分配空间保存之前的调用信息, 如果没有这句话后面的DBUG_RETURN 会有问题

 p->prepare_for_resend();                           //准备发送数据
  if(p->send_result_set_row(&l))                  //设置要送发的数据
{
   p->remove_last_row();
   DBUG_RETURN(TRUE);
  }
 thd->sent_row_count++;                            
  if(p->write())                                             //向客户端发送数据
   DBUG_RETURN(TRUE);
  else
   DBUG_RETURN(FALSE);
}

 

5. 多行数据的测试

DISPATCH ADDgao;           //这个是执行的命令
message   Position
gao    10
end    0
end    0
DISPATCH ADDxiao;         //这个是执行的命令
message   Position
delete   10
end    0
end    0
0 0