本文主要介绍如何在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”函数中的“case SQLCOM_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)

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

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

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

3. 

#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"); 
 

 
  field_list.push_back(new Item_empty_string("message", 255));   //注:这里是设置表头
   
 //注:这里是设置表头 
 
 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); 
 
}

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

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

 TEST  
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
  RESULT  
   
  TIME (ms) or COMMENT 
 
 -------------------------------------------------------------------------- 
 

 worker[1] Using MTR_BUILD_THREAD 300, with reserved ports 13000..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(new Item_empty_string("message", 255));  
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
 //这里是设置metadata 
 
   
  field_list.push_back(new Item_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(new Item_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进入了一个新的用户函数,并且在栈中
                                                                      
   
  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 ADD gao;  
   
   
   
   
   
   
   
   
   
   
 //这个是执行的命令 
 
 message  
   
    
 Position 
 
 gao  
   
    
 10 
 
 end  
   
    
 0 
 
 end  
   
    
 0 
 
 DISPATCH ADD xiao;  
   
   
   
   
   
   
   
   
 //这个是执行的命令 
 
 message  
   
    
 Position 
 
 delete  
   
    
 10 
 
 end  
   
    
 0 
 
 end  
   
    
 0