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

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没讲,我下一篇打算讲讲他是如何工作的。

相关文章

来源:http://www.postgres.cn/docs/11/ 4.1.1. 标识符和关键词 SQL标识符和关键词必须以一个...
来源:http://www.postgres.cn/docs/11/ 8.1. 数字类型 数字类型由2、4或8字节的整数以及4或8...
来源:http://www.postgres.cn/docs/11/ 5.1. 表基础 SQL并不保证表中行的顺序。当一个表被读...
来源:http://www.postgres.cn/docs/11/ 6.4. 从修改的行中返回数据 有时在修改行的操作过程中...
来源:http://www.postgres.cn/docs/11/ 13.2.1. 读已提交隔离级别 读已提交是PostgreSQL中的...
来源:http://www.postgres.cn/docs/11/ 9.7. 模式匹配 PostgreSQL提供了三种独立的实现模式匹...