我们来为MySQL添加一个函数,名为show disk_usage
mysql> show disk_usage;
+----------+-----------+
| Database | Size (Kb) |
+----------+-----------+
| test_row | 120400 |
+----------+-----------+
1 row in set (0.00 sec)
要修改新的函数,涉及到词法分析,我们先来修改sql/lex.h文件。
找到static SYMBOL symbols[] 这个结构体,添加一个”DISK_USAGE”这个词法,效果如下
{ "DISK", SYM(DISK_SYM)},
/*start*/
{ "DISK_USAGE", SYM(DISK_USAGE_SYM)},
/*end */
{ "DISTINCT", SYM(DISTINCT)}
于是词法分析的时候会DISK_USAGE这个词法当做一个token转化为内部枚举DISK_USAGE_SYM。
有新的词法,我们为新词法添加新语法,我们来修改sql/yacc.yy文件。
来到token区域,添加一个token,名字于lex.h一样,这样语法分析器bison才能知晓词法分析器flex传过来的token对应的枚举。
%token DISK_SYM
/*start*/
%token DISK_USAGE_SYM
/*end*/
%token DISTINCT
继续添加发现show disk_usage()语法匹配之后的行为
搜索关键字show: 添加新的行为
show:
/*start*/
SHOW DISK_USAGE_SYM
{
LEX *lex = Lex;
sql_command = SQLCOM_SHOW_DISK_USAGE;
}
| /*end*/
SHOW
到这里为止词法语法部分添加完毕。
SQLCOM_SHOW_DISK_USAGE产生什么效果呢,需要指向具体的函数。
在添加具体函数之前,还需要让SQLCOM_SHOW_DISK_USAGE成为一个合法的sql_command,我们需要修改sql/sql_lex.h。找到关键字enum enum_sql_command, 把SQLCOM_SHOW_DISK_USAGE作为一个enum添加进去
SQLCOM_SHOW_PROFILE,
SQLCOM_SHOW_PROFILES,
/*start*/
SQLCOM_SHOW_DISK_USAGE,
/*end*/
/*
When a command is added here, be sure it's also added in mysqld.cc
in "struct show_var_st status_vars[]= {" ...
*/
/* This should be the last !!! */
SQLCOM_END
};
接着还要在sql/mysqld.cc 里再添加一遍, 找到关键字SHOW_VAR com_status_vars[]= {
{"show_authors", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_AUTHORS]), SHOW_LONG_STATUS},
/*start*/
{"show_disk_usage", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_DISK_USAGE]), SHOW_LONG_STATUS},
/*end*/
{"show_binlog_events", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_BINLOG_EVENTS]), SHOW_LONG_STATUS},
不添加这部会出现编译时的ASSERT错误。
接着把SQLCOM_DISK_USAGE指向具体函数, 修改sql/sql_parse.cc,关键字mysql_execute_command
switch (lex->sql_command) {
/*start*/
case SQLCOM_SHOW_DISK_USAGE:
res = show_disk_usage_command(thd);
break;
/*end*/
case SQLCOM_SHOW_EVENTS:
好了终于指向了具体的函数show_disk_usage_command(),我们接着来实现这个函数。
在sql/mysql_priv.h添加一个申明
bool mysqld_help (THD *thd, const char *text);
/*start*/
bool show_disk_usage_command(THD *thd);
/* end */
void calc_sum_of_all_status(STATUS_VAR *to);
在sql/sql_show.cc添加一个具体的实现
bool show_disk_usage_command(THD *thd)
{
DBUG_ENTER("show_disk_usage");
List field_list;
List dbs;
Protocol *protocol = thd->protocol;
/*set fields*/
field_list.push_back(new Item_empty_string("Database", 50));
field_list.push_back(new Item_empty_string("Size (Kb)", 30));
if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS|Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
/*set data*/
protocol->prepare_for_resend();
protocol->store("test_row", system_charset_info);
protocol->store("1024000", system_charset_info);
if (protocol->write())
DBUG_RETURN(TRUE);
my_eof(thd);
DBUG_RETURN(FALSE);
}
/*end*/
bool mysqld_show_authors(THD *thd)
make clean; make;make install
好了,效果就可以看到了
mysql> show disk_usage;
+----------+-----------+
| Database | Size (Kb) |
+----------+-----------+
| test_row | 1024 |
+----------+-----------+
1 row in set (0.00 sec)
ps : 部分参考expert mysql
for douban: doubanclaimfdd64e647e42d240
觉得文章有用?立即:
和朋友一起 共学习 共进步!
猜您喜欢