MySQL的词法分析漫谈

这个链接上有点介绍,可以了解个大概:http://blog.imaginea.com/mysql-query-parsing/

关键点:

1. SQL解析包括语法分析器和词法分析器。

简便的做法是用bison/flex组合。不过MySQL的词法分析器是手工打造的。

语法分析器的入口函数是MYSQLparse,词法分析器的入口函数是MYSQLlex。

2. 词法分析中会检查token是否为关键字。

最直接的做法是弄个大的关键字数组,进行折半查找。MySQL在此做了些优化。

本文主要介绍的是这一部分。

考虑到关键字是一个只读的列表,对它做一个只读的查找树可以改善查找的性能。

产生查找树:

1. 读取关键字数组,产生一个Trie树。

2. 调整这棵树,并产生一个数组(也就是一个不用链表表示的树)。

使用查找树:

这个比较简单,直接看函数get_hash_symbol好了。

产生查找树,相关的Makefile规则:

In `sql/CMakeFiles/sql.dir/build.make‘:

sql/lex_hash.h: sql/gen_lex_hash

$(CMAKE_COMMAND) -E cmake_progress_report /home/zedware/Workspace/mysql/CMakeFiles $(CMAKE_PROGRESS_153)

@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --blue --bold "Generating lex_hash.h"

cd /home/zedware/Workspace/mysql/sql && ./gen_lex_hash > lex_hash.h

容易发现,最主要的函数就是`get_hash_symbol‘,它主要的调用关系为:

/* sql/lex_hash.h */

get_hash_symbol->sql_functions_map

get_hash_symbol->symbols_map

/* sql/sql_lex.cc */

find_keyword->get_hash_symbol

is_keyword->get_hash_symbol

is_lex_native_function->get_hash_symbol

文件"gen_lex_hash.cc"注释中的树的示例:

+-----------+-+-+-+

|       len |1|2|3|

+-----------+-+-+-+

|first_char |0|0|a|

|last_char  |0|0|d|

|link       |0|0|+|

|

V

+----------+-+-+-+--+

|    1 char|a|b|c|d |

+----------+-+-+-+--+

|first_char|d|0|0|0 |

|last_char |n|0|0|-1|

|link      |+|0|0|+ |

|     |

|     V

|  symbols[2] ( "DAY" )

V

+----------+--+-+-+-+-+-+-+-+-+-+--+

|    2 char|d |e|f|j|h|i|j|k|l|m|n |

+----------+--+-+-+-+-+-+-+-+-+-+--+

|first_char|0 |0|0|0|0|0|0|0|0|0|0 |

|last_char |-1|0|0|0|0|0|0|0|0|0|-1|

|link      |+ |0|0|0|0|0|0|0|0|0|+ |

|                    |

V                    V

symbols[0] ( "ADD" )  symbols[1] ( "AND" )

如果你还记得Trie树,理解起来会容易一点。下面是不同的输入数组对应的树。

i=0

+-----------+-+--+

|       len |1| 2|

+-----------+-+--+

|first_char |0|-1|

|last_char  |0| 0|

|char_tails |0| x|

|ithis      |0| 0|

|iresult    |0| 0|

|

&&

static SYMBOL symbols[] = {

{ "&&",   SYM(AND_AND_SYM)},

static uchar symbols_map[8]= {

0,   0,   1, 0,                    <=== 1 == symbols[]数组的元素个数,表示没找到

0,   0,   0, 0,                    <=== symbols[0]

};

i=1

+-----------+--+--+

|       len | 1| 2|

+-----------+--+--+

|first_char |-1|-1|

|last_char  | 0| 0|

|char_tails | x| x|

|ithis      | 0| 0|

|iresult    | 1| 0|

|  |

< &&

static SYMBOL symbols[] = {

{ "&&",   SYM(AND_AND_SYM)},

{ "<",    SYM(LT)},

static uchar symbols_map[8]= {

0,   0,   1, 0,                    <=== 1 < symbols[]数组的元素个数2,戫示找到的就是symbols[1]

0,   0,   0, 0,                    <=== symbols[0]

};

i=2

+-----------+--+--+

|       len | 1| 2|

+-----------+--+--+

|first_char |-1| &|

|last_char  | 0| <|

|char_tails | x| ^|

|ithis      | 0| 0|

|iresult    | 1| x|

|  |

<  |

|

+----------+--+--+   +--+

|    1 char| &|  |...| <|

+----------+--+--+   +--+

|first_char|-1| 0|   |-1|

|last_char | 0| 0|   | 0|

|char_tails| 0| 0|   | x|

|ithis     | 0| 0|   | 0|

|iresult   | 0| 0|   | 2|

|          |

&&        <=

static SYMBOL symbols[] = {

{ "&&",   SYM(AND_AND_SYM)},

{ "<",    SYM(LT)},

{ "<=",   SYM(LE)},

static uchar symbols_map[100]= {

0,   0,   1, 0,

‘&‘, ‘<‘, 2, 0,

0,   0,   0, 0,

0,   0,   3, 0,

0,   0,   3, 0,

0,   0,   3, 0,

0,   0,   3, 0,

0,   0,   3, 0,

0,   0,   3, 0,

0,   0,   3, 0,

0,   0,   3, 0,

0,   0,   3, 0,

0,   0,   3, 0,

0,   0,   3, 0,

0,   0,   3, 0,

0,   0,   3, 0,

0,   0,   3, 0,

0,   0,   3, 0,

0,   0,   3, 0,

0,   0,   3, 0,

0,   0,   3, 0,

0,   0,   3, 0,

0,   0,   3, 0,

0,   0,   3, 0,

0,   0,   2, 0,

};

i=3

+-----------+--+--+

|       len | 1| 2|

+-----------+--+--+

|first_char |-1| &|

|last_char  | 0| <|

|char_tails | x| ^|

|ithis      | 0| 0|

|iresult    | 1| x|

|  |

<  |

|

+----------+--+--+   +--+

|    1 char| &|  |...| <|

+----------+--+--+   +--+

|first_char|-1| 0|   |-1|

|last_char | 0| 0|   | 0|

|char_tails| 0| 0|   | x|

|ithis     | 0| 0|   | 0|

|iresult   | 0| 0|   | p|

|          |

&&         |

|

+----------+--+--+

|    2 char| =| >|

+----------+--+--+

|first_char|-1|-1|

|last_char | 0| 0|

|char_tails| x| x|

|ithis     | 0| 0|

|iresult   | 2| 3|

|  |

<=  <>

static SYMBOL symbols[] = {

{ "&&",   SYM(AND_AND_SYM)},

{ "<",    SYM(LT)},

{ "<=",   SYM(LE)},

{ "<>",   SYM(NE)},

static uchar symbols_map[108]= {

0,   0,   1, 0,

‘&‘, ‘<‘, 2, 0,

0,   0,   0, 0,

0,   0,   4, 0,

0,   0,   4, 0,

0,   0,   4, 0,

0,   0,   4, 0,

0,   0,   4, 0,

0,   0,   4, 0,

0,   0,   4, 0,

0,   0,   4, 0,

0,   0,   4, 0,

0,   0,   4, 0,

0,   0,   4, 0,

0,   0,   4, 0,

0,   0,   4, 0,

0,   0,   4, 0,

0,   0,   4, 0,

0,   0,   4, 0,

0,   0,   4, 0,

0,   0,   4, 0,

0,   0,   4, 0,

0,   0,   4, 0,

0,   0,   4, 0,

‘=‘, ‘>‘, 25, 0,

0,   0,   2, 0,

0,   0,   3, 0,

};

可以看到,数组表示中存在一定的空间浪费。要是不怕麻烦,我们还可以去榨出一点油水来。

MySQL的词法分析漫谈,布布扣,bubuko.com

时间: 2024-10-14 07:37:16

MySQL的词法分析漫谈的相关文章

AF攻防研究之四个层次Bypass WAF

从架构.资源.协议和规则4个层次研究绕过WAF的技术,助于全方位提升WAF防御能力. 绕过WAF的相关技术研究是WAF攻防研究非常重要的一部分,也是最有趣的部分,所以我在写WAF攻防时先写攻击部分.还是那句老话“不知攻焉知防”,如果连绕过WAF方法都不知道,怎么保证WAF能保护后端服务的安全.在我看来,WAF的绕过技术的研究将不断驱动防御水平提高. 以前一些WAF bypass的文章更像CASE的整理,都把焦点放在了规则对抗层面.绕过WAF规则,更像是正面对抗,属于下策.一直关注规则层面的绕过,

84-虚拟机的词法解析

84-虚拟机的词法解析 语言从广义上来讲是人们进行沟通交流的各种表达符号.每种语言都有专属于自己的符号,表达方式和规则. 就编程语言来说,它也是由特定的符号,特定的表达方式和规则组成. 语言的作用是沟通,不管是自然语言,还是编程语言,它们的区别在于自然语言是人与人之间沟通的工具, 而编程语言是人与机器之间的沟通渠道.相对于自然语言,编程语言的历史还非常短, 虽然编程语言是站在历史巨人的基础上创建的,但是它还很小,还是一个小孩. 它只能按编程人员所给的指令翻译成对应的机器可以识别的语言.它就相当于

漫谈MySQL primaryKey

主键没有着明确的概念定义,其是索引的一种,并且是唯一性索引的一种,且必须定义为“PRIMARY KEY”,是只可意会不可言传的东西.下面让我用通俗,甚至有些低俗的语言为您简单介绍一下MySQL的主键. 简单描述: 主键不能重复, 就像QQ的用户名,有N个叫“虫zi”的网友,可是他们的QQ号码是不一样的,也就是说真正标识一个QQ的身份是“QQ号码”.还有那万恶的身份证,无论 “张三,李四,王二麻子”这些都不能代表一个人,真正能代表一个人确切身份的就是那个“天朝特色的万恶的身份证”,相当于在杀猪的时

MySQL &#183; 性能优化&#183; InnoDB buffer pool flush策略漫谈

MySQL · 性能优化· InnoDB buffer pool flush策略漫谈 背景 我们知道InnoDB使用buffer pool来缓存从磁盘读取到内存的数据页.buffer pool通常由数个内存块加上一组控制结构体对象组成.内存块的个数取决于buffer pool instance的个数,不过在5.7版本中开始默认以128M(可配置)的chunk单位分配内存块,这样做的目的是为了支持buffer pool的在线动态调整大小. Buffer pool的每个内存块通过mmap的方式分配内

漫谈MySql中的事务

最近一直在做订单类的项目,使用了事务.我们的数据库选用的是MySql,存储引擎选用innoDB,innoDB对事务有着良好的支持.这篇文章我们一起来扒一扒事务相关的知识. 为什么要有事务? 事务广泛的运用于订单系统.银行系统等多种场景.如果有以下一个场景:A用户和B用户是银行的储户.现在A要给B转账500元.那么需要做以下几件事: 1. 检查A的账户余额>500元: 2. A账户扣除500元: 3. B账户增加500元: 正常的流程走下来,A账户扣了500,B账户加了500,皆大欢喜.那如果A账

【MySQL】漫谈MySQL中的事务及其实现

最近一直在做订单类的项目,使用了事务.我们的数据库选用的是MySQL,存储引擎选用innoDB,innoDB对事务有着良好的支持.这篇文章我们一起来扒一扒事务相关的知识. 为什么要有事务? 事务广泛的运用于订单系统.银行系统等多种场景.如果有以下一个场景:A用户和B用户是银行的储户.现在A要给B转账500元.那么需要做以下几件事: 1. 检查A的账户余额>500元: 2. A账户扣除500元: 3. B账户增加500元: 正常的流程走下来,A账户扣了500,B账户加了500,皆大欢喜.那如果A账

mysql数据库漫谈

mysql数据库有一个特点,即所有 sql 语句中的DDL和DML(不包含select)语句执行成功后都会显示"Query OK". 与其他数据库管理系统不同,mysql数据库管理系统提供了一个名为存储引擎的概念.由于存储引擎是以插件形式被mysql数据库软件引入的,所以可以根据实际应用.实际需要来自由选择相应的存储引擎.下表是mysql常见存储引擎的特点: 我们最常见的两种存储引擎是MyISAM和InnoDB. 修改存储引擎:方法一,"开始"--"程序&

mysql索引结构原理、性能分析与优化

原文  http://wulijun.github.com/2012/08/21/mysql-index-implementation-and-optimization.html 第一部分:基础知识 索引 官方介绍索引是帮助MySQL高效获取数据的数据结构.笔者理解索引相当于一本书的目录,通过目录就知道要的资料在哪里, 不用一页一页查阅找出需要的资料. 唯一索引(unique index) 强调唯一,就是索引值必须唯一. 创建索引: create unique index 索引名 on 表名(列

由浅入深探究mysql索引结构原理、性能分析与优化

转载自:http://www.phpben.com/?post=74 第一部分:基础知识: 索引 官方介绍索引是帮助MySQL高效获取数据的数据结构.笔者理解索引相当于一本书的目录,通过目录就知道要的资料在哪里,不用一页一页查阅找出需要的资料.关键字index ------------------------------------------------------------- 唯一索引 强调唯一,就是索引值必须唯一,关键字unique index 创建索引: 1.create unique