本节简单介绍了PostgreSQL在执行parse中重要的两个数据结构:SelectStmt&Value.

一、数据结构

SelectStmt
“simple” SELECT可转换为SelectStmt节点.包含集合操作(UNION, INTERSECT, EXCEPT)的查询通过SelectStmt节点树来表示,在这棵树中,叶子节点是SELECTs组件,而内部节点表示UNION, INTERSECT, or EXCEPT操作符.内部节点和叶子节点是相同的节点类型.

/* ---------------------- * Select Statement * * A "simple" SELECT is represented in the output of gram.y by a single * SelectStmt node; so is a VALUES construct. A query containing set * operators (UNION, INTERSECT, EXCEPT) is represented by a tree of SelectStmt * nodes, in which the leaf nodes are component SELECTs and the internal nodes * represent UNION, INTERSECT, or EXCEPT operators. Using the same node * type for both leaf and internal nodes allows gram.y to stick ORDER BY, * LIMIT, etc, clause values into a SELECT statement without worrying * whether it is a simple or compound SELECT. * * "simple" SELECT可转换为SelectStmt节点. * 包含集合操作(UNION, INTERSECT, EXCEPT)的查询通过SelectStmt节点树来表示, * 在这棵树中,叶子节点是SELECTs组件,而内部节点表示UNION, INTERSECT, or EXCEPT操作符. * 内部节点和叶子节点是相同的节点类型. * ---------------------- */typedef enum SetOperation{ SETOP_NONE = 0, SETOP_UNION, SETOP_INTERSECT, SETOP_EXCEPT} SetOperation;typedef struct SelectStmt{ NodeTag type; /* * These fields are used only in "leaf" SelectStmts. * "叶子"SelectStmts节点使用的字段 */ //NULL,DISTINCT ON表达式链表,或者所有(SELECT DISTINCT)的lcons(NIL,NIL) List *distinctClause; /* NULL, list of DISTINCT ON exprs, or * lcons(NIL,NIL) for all (SELECT DISTINCT) */ //SELECT INTO的target IntoClause *intoClause; /* target for SELECT INTO */ //目标链表(元素为ResTarget) List *targetList; /* the target list (of ResTarget) */ //FROM子句 List *fromClause; /* the FROM clause */ //WHERE Node *whereClause; /* WHERE qualification */ //GROUP BY 子句 List *groupClause; /* GROUP BY clauses */ //HAVING条件表达式 Node *havingClause; /* HAVING conditional-expression */ //窗口函数链表 List *windowClause; /* WINDOW window_name AS (...), ... */ /* * 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. * 如果"叶子"节点表示VALUES链表,则上述字段均为NULL,而该字段会存储相关信息. */ List *valuesLists; /* untransformed list of expression lists */ /* * These fields are used in both "leaf" SelectStmts and upper-level * SelectStmts. * 下面这些字段用于"left"节点和上层节点 */ //排序子句 List *sortClause; /* sort clause (a list of SortBy's) */ //limit偏移 Node *limitOffset; /* # of result tuples to skip */ //limit个数 Node *limitCount; /* # of result tuples to return */ //FOR UPDATE List *lockingClause; /* FOR UPDATE (list of LockingClause's) */ //CTE WithClause *withClause; /* WITH clause */ /* * These fields are used only in upper-level SelectStmts. * 下面这些字段用于高层SelectStmts */ //操作类型 SetOperation op; /* type of set op */ bool all; /* ALL specified? */ //左边树 struct SelectStmt *larg; /* left child */ //右边树 struct SelectStmt *rarg; /* right child */ /* Eventually add fields for CORRESPONDING spec here */} SelectStmt;

Value
相同的Value结构体用于5中节点类型:T_Integer, T_Float, T_String, T_BitString, T_Null

/*------------------------------------------------------------------------- * * value.h * interface for Value nodes * * * Copyright (c) 2003-2019, PostgreSQL Global Development Group * * src/include/nodes/value.h * *------------------------------------------------------------------------- */#ifndef VALUE_H#define VALUE_H#include "nodes/nodes.h"/*---------------------- * Value node * * The same Value struct is used for five node types: T_Integer, * T_Float, T_String, T_BitString, T_Null. * 相同的Value结构体用于5中节点类型:T_Integer, T_Float, T_String, T_BitString, T_Null * * Integral values are actually represented by a machine integer, * but both floats and strings are represented as strings. * Using T_Float as the node type simply indicates that * the contents of the string look like a valid numeric literal. * 整型值实际上通过机器integer来表示,但floats和strings均使用字符串来表示. * 使用T_Float作为节点类型只是简单的表示字符串中的内存看似有效的数值字面量. * * (Before Postgres 7.0, we used a double to represent T_Float, * but that creates loss-of-precision problems when the value is * ultimately destined to be converted to NUMERIC. Since Value nodes * are only used in the parsing process, not for runtime data, it's * better to use the more general representation.) * (在PG 7.0以前,使用double来表示T_Float,但会出现精度丢失的问题) * * Note that an integer-looking string will get lexed as T_Float if * the value is too large to fit in an 'int'. * 注意 : 看似整型字符串在不能使用int存储的情况下会在语义上视为T_Float * * Nulls, of course, don't need the value part at all. * Nulls,不需要值 *---------------------- */typedef struct Value{ NodeTag type; /* tag appropriately (eg. T_String) */ union ValUnion { int ival; /* machine integer */ char *str; /* string */ } val;} Value;#define intVal(v) (((Value *)(v))->val.ival)#define floatVal(v) atof(((Value *)(v))->val.str)#define strVal(v) (((Value *)(v))->val.str)extern Value *makeInteger(int i);extern Value *makeFloat(char *numericStr);extern Value *makeString(char *str);extern Value *makeBitString(char *str);#endif /* VALUE_H */二、源码解读

N/A

三、跟踪分析

测试SQL语句:

-- 用于测试的查询语句testdb=# select t_dwxx.dwmc,t_grxx.grbh,t_grxx.xm,t_jfxx.ny,t_jfxx.jetestdb-# from t_dwxx,t_grxx,t_jfxxtestdb-# where t_dwxx.dwbh = t_grxx.dwbh testdb-# and t_grxx.grbh = t_jfxx.grbhtestdb-# and t_dwxx.dwbh IN ('1001','1002')testdb-# order by t_grxx.grbhtestdb-# limit 8; dwmc | grbh | xm | ny | je -----------+------+------+--------+-------- X有限公司 | 901 | 张三 | 201801 | 401.3 X有限公司 | 901 | 张三 | 201802 | 401.3 X有限公司 | 901 | 张三 | 201803 | 401.3 Y有限公司 | 902 | 李四 | 201801 | 513.1 Y有限公司 | 902 | 李四 | 201802 | 513.3 Y有限公司 | 902 | 李四 | 201804 | 513.3 Y有限公司 | 903 | 王五 | 201801 | 372.22 Y有限公司 | 903 | 王五 | 201804 | 372.22(8 rows)

样例数据如下:

...(gdb) p *(RawStmt *)(raw_parsetree_list->head.data->ptr_value)$7 = {type = T_RawStmt, stmt = 0x1a48c00, stmt_location = 0, stmt_len = 232}(gdb) p *((RawStmt *)(raw_parsetree_list->head.data->ptr_value))->stmt$8 = {type = T_SelectStmt}###### 实际类型SelectStmt (gdb) p *(SelectStmt *)((RawStmt *)(raw_parsetree_list->head.data->ptr_value))->stmt$16 = {type = T_SelectStmt, distinctClause = 0x0, intoClause = 0x0, targetList = 0x1a47b18, fromClause = 0x1a48900, whereClause = 0x1a48b40, groupClause = 0x0, havingClause = 0x0, windowClause = 0x0, valuesLists = 0x0, sortClause = 0x1afd858, limitOffset = 0x0, limitCount = 0x1afd888, lockingClause = 0x0, withClause = 0x0, op = SETOP_NONE, all = false, larg = 0x0, rarg = 0x0}四、参考资料

N/A