2008年12月13日星期六

PostgreSql源码学习(7)

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

没有评论: