(接上篇)
问题就出在find_command函数这里,让我们find_command干了什么事。它并没有像我们想像的那样在长格式的系统命令的行尾添加分号不会影响命令的正常执行。
Code:
客户端没有把source pp#idhuishou.sql;当成命令处理,接下来就交给了add_line来处理了,而add_line又会把井号后面的内容全部当做注释处理掉,不会传给MySQL然后接着等待另一个分号的输入以做为语句的结束,因此source pp#idhuishou.sql;就变成了source pp。下面就是add_line函数的代码:
如果输入的系统命令结尾带有分号find_command就会将系统命令当成普通的SQL语句来处理,不使用单独的处理函数,这样会不会有问题呢?下面以com_source为例,看一看MySQL是如何处理SOURCE命令的。
看到这里还有个疑问,既然MySQL的系统命令分别有单独的函数进行处理,
static int com_source(String *buffer, char *line) { ... ... error= read_and_execute(false);//以非交互模式嵌套调用read_and_execute函数... ...
return error;
//可见com_source并没做什么实事,检测了一下将要处理的文件的可读性,
//和普通SQL语句一样把又任务交给了read_and_execute结尾处的com_go函数来处理
}下面列举所有的MySQL系统命令如下:
mysql> ?
For information about MySQL products and services, visit:http://www.mysql.com/
For developer information, including the MySQL Reference Manual, visit:http://dev.mysql.com/ To buy MySQL Network Support, training, or other products, visit:https://shop.mysql.com/ List of all MySQL commands: Note that all text commands must be first on line and end with ';' ? (\?) Synonym for `help'. clear (\c) Clear command. connect (\r) Reconnect to the server. Optional arguments are db and host. delimiter (\d) Set statement delimiter. NOTE: Takes the rest of the line as new delimiter. edit (\e) Edit command with $EDITOR. ego (\G) Send command to mysql server, display result vertically. exit (\q) Exit mysql. Same as quit. go (\g) Send command to mysql server. help (\h) Display this help. nopager (\n) Disable pager, print to stdout. notee (\t) Don't write into outfile. pager (\P) Set PAGER [to_pager]. Print the query results via PAGER. print (\p) Print current command. prompt (\R) Change your mysql prompt. quit (\q) Quit mysql. rehash (\#) Rebuild completion hash. source (\.) Execute an SQL script file. Takes a file name as an argument. status (\s) Get status information from the server. system (\!) Execute a system shell command. tee (\T) Set outfile [to_outfile]. Append everything into given outfile. use (\u) Use another database. Takes database name as argument. charset (\C) Switch to another charset. Might be needed for processing binlog with multi-byte charsets. warnings (\W) Show warnings after every statement. nowarning (\w) Don't show warnings after every statement. For server side help, type 'help contents'
总结: 要清楚的知道哪些语句是系统命令,哪些语句是标准的SQL语句,系统命令结尾最好不要有分号。
MySQL手册也有盲点,还是代码靠谱。
tatic bool add_line(String &buffer,char *line,char *in_string,
bool *ml_comment)
{
... ...
else if (!*ml_comment && (!*in_string && (inchar == '#' ||
//就是这里把"#"号"-- "等后面的内容都当做注释处理掉了
inchar == '-' && pos[1] == '-' && my_isspace(charset_info,pos[2])))) break; // comment to end of line ... ... }
static COMMANDS *find_command(char *name,char cmd_char){ ... ...
if (strstr(name, "\\g") || (strstr(name, delimiter) &&
//语句中含有分号,\g或通过delimiter指定的其他分隔符,客户端就不会把这条语句当成系统命令。
//问题就出在这里,当find_command函数看到分号或\g无论如何它都不会把语句当成系统命令来处理
DBUG_RETURN((COMMANDS *) 0);
//判断不是系统命令就返回一个空指针
if ((end=strcont(name," \t"))) { len=(uint) (end - name); while (my_isspace(charset_info,*end)) end++; if (!*end)end=0;
// no arguments to function
} else len=(uint) strlen(name); ... ... }