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

前端之家收集整理的这篇文章主要介绍了postgresql查询分析源码分析-流程前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

postgresql version :9.4.4

源码路径:src/backend/parser

@H_301_5@

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

@H_301_5@

现在看的源码是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,如果我们想添加一个关键字,可以在这个头文件添加。(注意添加顺序哦)

@H_301_5@

查询分析的基本流程:

@H_301_5@

@H_301_5@

@H_301_5@

我们现在来看看源码:

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

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

@H_301_5@

再gdb到这个进程: @H_301_5@

@H_301_5@

(gdb) b exec_simple_query

Breakpoint 1 at 0x7d35c0: file postgres.c,line 883.

(gdb) c

Continuing.

在exec_simple_query 打个断点。

@H_301_5@

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

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

(gdb) p query_string

$1 = 0x1a22e58 "select * from sangli;"

next......

@H_301_5@

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

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

@H_301_5@

我们进来函数,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)

@H_301_5@

@H_301_5@

我们看看头文件
/*
 * 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;
@H_301_5@ 上面的yyextra就是base_yy_extra_type。

@H_301_5@

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

@H_301_5@

targetList:

@H_301_5@

上面的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.

@H_301_5@

fromClause:

@H_301_5@

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

@H_301_5@

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

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

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

大概流程就是这样,这个里面最主要的是flex&bison没讲,我下一篇打算讲讲他是如何工作的。

猜你在找的Postgre SQL相关文章