话说 查询“ select cname, comp from test1, test2 where test1.id=test2.id; ” 发送到服务器端, 走查询分支 exec_simple_query ,先调用 start_xact_command 初始化了事务管理相关对象和资源,接着调用 pg_parse_query ,通过 Lex 和 Yacc 对传入 SQL 语句进行词法语法解析,生成解析树。下来调用 GetTransactionSnapshot 方法做内存快照,然后调用 pg_analyze_and_rewrite 方法,进行语义分析把 parsetree 转换成 querytree ,然后对该 querytree 进行重写。
1
下面是对 parseetree 进行语义分析和查询重写的调用序列图。
Postgres 服务进程简查之语义分析和查询重写调用序列图
上图红色方框中显示了对 parsetree 进行语义分析和查询重写的方法调用过程,在 parse_analyze 方法中对 parsetree 进行语义分析,生成 querytree ,在 pg_rewrite_query 方法中对前面生成的 q uerytree 进一步进行修改,最后把 querytree 返回给 exec_simple_query 。在 parse_analyze 方法中根据这个例子中语句生成的 节点类型 T_SelectStmt 走 transformSelectStmt 分支,分别调用 transformFromClause 、 transformTargetList 、 transformWhereClause 方法处理 from 、目标属性、 where 子句。处理完后把目标传到 pg_rewrite_query 方法,在 pg_rewrite_query 方法里利用规则 /rule 对 querytree 中对应的目标进行重写,规则是查询重写处理的关键, pg 的规则中 pg_write 系统表中。规则和触发器相似,都可以在某种条件下激活,可执行原命令之外的动作,区别是触发器多涉及到每个元组都执行一次,而规则对整个查询树 querytree 进行修改或额外的查询。一个语句如果涉及多个元组,规则一般比触发器效率高,但触发器更容易理解。
这部分内容涉及到结构和处理及代码量相当多,在这就不列举了,有兴趣的根据方法调用流程图看源码吧,下面给出处理完的结果 querytree 结构图。
例子里查询语句对应的 querytree 结构图
把这个例子再重复一下:
create table test1 (ID numeric(10), cname varchar(30));
create table test2 (ID numeric(10), comp varchar(30));
select cname,comp from test1,test2 where test1.id=test2.id;
上面的图《例子里查询语句对应的 querytree 结构图》就是 SQL 语句“ select cname,comp from test1,test2 where test1.id=test2.id ”在 pg 里产生的 querytree 。
pg 输出的 querytree 如下:
2011-11-23 06:57:39 HKT DETAIL: (
{QUERY
:commandType 1
:querySource 0
:canSetTag true
:utilityStmt <>
:resultRelation 0
:intoClause <>
:hasAggs false
:hasWindowFuncs false
:hasSubLinks false
:hasDistinctOn false
:hasRecursive false
:hasModifyingCTE false
:hasForUpdate false
:cteList <>
:rtable (
{RTE
:alias <>
:eref
{ALIAS
:aliasname test1
:colnames ("id" "cname")
}
:rtekind 0
:relid 16394
:relkind r
:inh true
:inFromCl true
:requiredPerms 2
:checkAsUser 0
:selectedCols (b 9 10)
:modifiedCols (b)
}
{RTE
:alias <>
:eref
{ALIAS
:aliasname test2
:colnames ("id" "comp")
}
:rtekind 0
:relid 16397
:relkind r
:inh true
:inFromCl true
:requiredPerms 2
:checkAsUser 0
:selectedCols (b 9 10)
:modifiedCols (b)
}
)
:jointree
{FROMEXPR
:fromlist (
{RANGETBLREF
:rtindex 1
}
{RANGETBLREF
:rtindex 2
}
)
:quals
{OPEXPR
:opno 1752
:opfuncid 1718
:opresulttype 16
:opretset false
:opcollid 0
:inputcollid 0
:args (
{VAR
:varno 1
:varattno 1
:vartype 1700
:vartypmod 655364
:varcollid 0
:varlevelsup 0
:varnoold 1
:varoattno 1
:location 41
}
{VAR
:varno 2
:varattno 1
:vartype 1700
:vartypmod 655364
:varcollid 0
:varlevelsup 0
:varnoold 2
:varoattno 1
:location 50
}
)
:location 49
}
}
:targetList (
{TARGETENTRY
:expr
{VAR
:varno 1
:varattno 2
:vartype 1043
:vartypmod 34
:varcollid 100
:varlevelsup 0
:varnoold 1
:varoattno 2
:location 7
}
:resno 1
:resname cname
:ressortgroupref 0
:resorigtbl 16394
:resorigcol 2
:resjunk false
}
{TARGETENTRY
:expr
{VAR
:varno 2
:varattno 2
:vartype 1043
:vartypmod 34
:varcollid 100
:varlevelsup 0
:varnoold 2
:varoattno 2
:location 13
}
:resno 2
:resname comp
:ressortgroupref 0
:resorigtbl 16397
:resorigcol 2
:resjunk false
}
)
:returningList <>
:groupClause <>
:havingQual <>
:windowClause <>
:distinctClause <>
:sortClause <>
:limitOffset <>
:limitCount <>
:rowMarks <>
:setOperations <>
:constraintDeps <>
}
)
就到这儿吧。
------------
转载请注明出处,来自博客:
blog.csdn.net/beiigang
beigang.iteye.com