您的位置:首页 > 数据库

postgresql查询分析源码分析-流程

2015-12-14 23:23 501 查看
postgresql version :9.4.4

源码路径:src/backend/parser

所谓查询分析就是把SQL查询语句生成查询树。查询分析是查询编译的第一个模块。主要包括:词法分析,语法分析和语义分析这三个部分。

现在看的源码是9.4.4版本,在9.0词法分析借用了lex,语法分析是yacc。现在是升级的flex跟bison。

在postgresql中,对应的是src/backend/parser/gram.y&scan.l,这2个文件在编译的时候会生成gram.c/h,scan.c

关键字是在src/include/parser/kwlist.h,如果我们想添加一个关键字,可以在这个头文件添加。(注意添加顺序哦)

查询分析的基本流程:



我们现在来看看源码:

首先我们创建一张测试表,插入一条数据.

create table sangli(x text,y text,z bigint);
insert into sangli(x,y,z) values('x','y',99);


再gdb到这个进程:



(gdb) b exec_simple_query
Breakpoint 1 at 0x7d35c0: file postgres.c, line 883.
(gdb) c
Continuing.
在exec_simple_query 打个断点。



我们进入了这个函数,可以进行调试跟踪了。

首先,SQL命令为:query_string=select * from sangli;

(gdb) p query_string
$1 = 0x1a22e58 "select * from sangli;"
next......

我们主要是看方法pg_parse_query(const char *query_string)这个就是parse SQL语句函数。这个函数返回个List,这个List是个parsetree.

这个List的返回值类型为:SelectStmt



我们进来函数,raw_parser(query_string),这个函数就是词法的语法分析的入口函数,这个会生成一个未分析的语法解析树。返回值是个yyextra.parsetree;

/*
29│  * raw_parser
30│  *              Given a query in string form, do lexical and grammatical analysis.
31│  *
32│  * Returns a list of raw (un-analyzed) parse trees.
33│  */
34│ List *
35│ raw_parser(const char *str)


我们看看头文件:

/*
* The YY_EXTRA data that a flex scanner allows us to pass around.  Private
* state needed for raw parsing/lexing goes here.
*/
typedef struct base_yy_extra_type
{
/*
* Fields used by the core scanner.
*/
core_yy_extra_type core_yy_extra;

/*
* State variables for base_yylex().
*/
bool		have_lookahead; /* is lookahead info valid? */
int			lookahead_token;	/* one-token lookahead */
core_YYSTYPE lookahead_yylval;		/* yylval for lookahead token */
YYLTYPE		lookahead_yylloc;		/* yylloc for lookahead token */

/*
* State variables that belong to the grammar.
*/
List	   *parsetree;		/* final parse result is delivered here */
} base_yy_extra_type;


上面的yyextra就是base_yy_extra_type。

targetList&fromClause我们来看看是什么东西。

targetList:



上面的gdb内容是:

p *(A_Star*)(*(ColumnRef*)(*(ResTarget*)(*(SelectStmt*)yyextra.parsetree->head->data->ptr_value)->targetList->head->data->ptr_value)->val)->fields->head->data->ptr_value
什么是A_Star?

我们查询语句select * from sangli;

这个*就是A_Star类型。这个应该很直观就能知道的。这样我们就知道什么是targetList.

fromClause:



很清楚,relname="sangli" 这个就是表的名称。别的参数可能在后面会重写的时候会赋值,可能没有.

这样pg_parse_query执行完毕,返回raw_parsetree_list.

其实这里还没有到返回Query,这个具体是在pg_analyze_and_rewrite里面返回的。

而这部分最主要的就是解析SQL文本。后面的analyze&rewrite 都是通过这里返回的parsetree进行操作的。

大概流程就是这样,这个里面最主要的是flex&bison没讲,我下一篇打算讲讲他是如何工作的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: