PG源码之parser(4)
前文已经大概描述了PGSQL,在解析SQL语句时所做的工作,接下来需要对在这个过程中的一些主要文件进行分析。
主要分析文件:
// 基础节点定义
src/include/nodes/nodes.h
// SQL语句被解析后得到的节点结构体定义
//SQL语句经过parser解析后都先对应该该文件的一个struct
src/include/nodes/parsenodes.h
// List定义
src/include/nodes/pg_list.h
// List实现
src/backend/nodes/list.c
// utility Stmt运行文件
src/backend/tcop/utility.c
// SQL analyze and rewrite
src/backend/parser/analyze.c
PostgreSQL用一种非常简单的形式实现了类似C++的继承,请看nodes.h :
typedef struct Node
{
NodeTag type;
} Node;
然后请看:parsenodes.h
假设有一个create table的sql:
create table test (name varchar(100, pass varchar(100));
将会被解析到如下structure:
typedef struct CreateStmt
{
NodeTag type;
RangeVar *relation; /* 关系名*/
List *tableElts; /* 列定义*/
List *inhRelations; /*表继承关系(PG里的继承) */
List *constraints; /* 约束条件 */
List *options; /*其他的可选条件*/
OnCommitAction oncommit; /* 提交时做的事情 */
char *tablespacename; /* 表空间*/
} CreateStmt;
以下是select语句对应的结构体:
typedef struct SelectStmt
{
NodeTag type;
/*
* These fields are used only in "leaf" SelectStmts.
*/
List *distinctClause; /* 处理distinct关键字 */
IntoClause *intoClause; /*处理select into /create table tbn as select ... */
List *targetList; /* 列*/
List *fromClause; /* from 子句*/
Node *whereClause; /* WHERE条件子句 */
List *groupClause; /* GROUP BY子句*/
Node *havingClause; /* HAVING 子句 */
/*
* In a "leaf" node representing a VALUES list, the above fields are all
* null, and instead this field is set. Note that the elements of the
* sublists are just expressions, without ResTarget decoration. Also note
* that a list element can be DEFAULT (represented as a SetToDefault
* node), regardless of the context of the VALUES list. It's up to parse
* analysis to reject that where not valid.(这段话的意思是valuesLists只在叶查询节点里出 * 现,就是最内层的子查询)
*/
List *valuesLists; /*表达式值列表*/
/*
* These fields are used in both "leaf" SelectStmts and upper-level
* SelectStmts.
*/
List *sortClause; /* 排序*/
Node *limitOffset; /* 从第几个开始limit子句的第一个参数 */
Node *limitCount; /* 到哪里结束limit子句的第二个参数*/
List *lockingClause; /* FOR UPDATE (list of LockingClause's) */
/*
* These fields are used only in upper-level SelectStmts.
*/
SetOperation op; /*set操作的类型*/
bool all; /*因该是处理any关键字的*/
struct SelectStmt *larg; /* left child */
struct SelectStmt *rarg; /* right child */
/* Eventually add fields for CORRESPONDING spec here */
} SelectStmt;
这上面是两个对应于create语句和select语句的结构体,对应于其他语句的结构体,也都可以在这个文件里找到,这两个结构体里面各个成员变量的含义我已经做了注释。这两个struct的第一个元素都是type(NodeTag)。PG的很多struct的第一个元素都是NodeTag,这样在函数中传递指针变量时,可以很简单的把参数设置成:Node*。说简单点,其实有点像是所有的struct都继承了Node这个struct。
在nodes.h中有每个Node的值的定义,比如:上面说的CreateStmt的type的值就是:T_CreateStmt。其他的每个node的定义也可以在这个文件里找到。
接下来需要看看的是链表,链表在pg_list.h中有定义:
typedef struct List
{
NodeTag type; /* T_List, T_IntList, or T_OidList */
int length;
ListCell *head;
ListCell *tail;
} List;
可以看到,List的定义是基于基类Node来进行的。
常用的List操作函数有:
//取List第一个元素
ListCell *y = list_head(List *l);
//得到List的元素个数
list_length(List *l);
// 遍历List
foreach(cell, l)
{
…
}
其他的很多函数具体可以参考pg_list.h和list.c
异星工厂太空时代游戏总结
1 天前
没有评论:
发表评论