这里把规范谓词表达式的部分就整理完了,阅读的顺序如下:
@H_404_15@一、PostgreSQL代码分析,查询优化部分,canonicalize_qual
二、PostgreSQL代码分析,查询优化部分,pull_ands()和pull_ors()
三、PostgreSQL代码分析,查询优化部分,process_duplicate_ors
- /*
- * canonicalize_qual
- * Convert a qualification expression to the most useful form.
- *
- * The name of this routine is a holdover from a time when it would try to
- * force the expression into canonical AND-of-ORs or OR-of-ANDs form.
- * Eventually,we recognized that that had more theoretical purity than
- * actual usefulness,and so now the transformation doesn't involve any
- * notion of reaching a canonical form.
- *
- * NOTE: we assume the input has already been through eval_const_expressions
- * and therefore possesses AND/OR flatness. Formerly this function included
- * its own flattening logic,but that requires a useless extra pass over the
- * tree.
- *
- * Returns the modified qualification.
- */
- /*
- * 对WHERE语句或ON语句中的条件进行规范化,从集合的角度对AND和OR两个操作做合并分解。
- */
- Expr *
- canonicalize_qual(Expr *qual)
- {
- Expr *newqual;
- /* Quick exit for empty qual */
- if (qual == NULL)
- return NULL;
- /*
- * Pull up redundant subclauses in OR-of-AND trees. We do this only
- * within the top-level AND/OR structure; there's no point in looking
- * deeper.
- */
- /*
- * 查找重复的OR操作,即化简条件语句。
- * 假设WHERE条件为:
- * (A=1 AND B=1) OR (A=1 AND C=1)
- * 可以化简为:
- * A=1 AND (B=1 OR C=1)
- *
- * 另外,这个函数中做了将树状的AND或OR语句平面化(flatten,或拉平)的工作,
- * 这两个工作主要体现在pull_ands()和pull_ors()两个函数中。
- */
- newqual = find_duplicate_ors(qual);
- return newqual;
- }
- /*
- * find_duplicate_ors
- * Given a qualification tree with the NOTs pushed down,search for
- * OR clauses to which the inverse OR distributive law might apply.
- * Only the top-level AND/OR structure is searched.
- *
- * Returns the modified qualification. AND/OR flatness is preserved.
- */
- static Expr *
- find_duplicate_ors(Expr *qual)
- {
- /*
- * “分支一:or_clause”
- *
- * 如果WHERE表达式中的主操作是OR,例如是如下形式:
- * A=1 OR B=1 OR (C=1 AND D=1)
- * 那么参数qual指针实际指向一个BoolExpr结构体。
- typedef struct BoolExpr
- {
- Expr xpr; = 略
- BoolExprType boolop; = OR_EXPR,即对下面的3个进行OR操作
- List *args; = 3个,分别是A=1和 B=1和(C=1 AND D=1)
- } BoolExpr;
- *
- * 这里的args是一个list,其中的3个元素的类型分别如下:
- * 第一个是比较操作,类型是OpExpr
- * 第二个是比较操作,类型是OpExpr
- * 第三个是AND操作,是一个AND_EXPR类型的BoolExpr,递归调用时会处理
- *
- * 张大明白的blog:http://blog.csdn.net/shujiezhang
- */
- if (or_clause((Node *) qual))
- {
- List *orlist = NIL;
- ListCell *temp;
- /* Recurse */
- /*
- * 对BoolExpr中的三个条件分别进行递归处理。
- * 在这里需要重点关注上例中的AND_EXPR类型的BoolExpr,因为在递归调用中,他将
- * 触发下一个分支(分支二)。
- */
- foreach(temp,((BoolExpr *) qual)->args)
- orlist = lappend(orlist,find_duplicate_ors(lfirst(temp)));
- /*
- * Don't need pull_ors() since this routine will never introduce an OR
- * where there wasn't one before.***这个原因没理解。***
- */
- /* 详情见《Postgresql代码分析,查询优化部分,process_duplicate_ors》博文*/
- return process_duplicate_ors(orlist);
- }
- /*
- * “分支二:and_clause”
- *
- * 这里主要做了两个操作:
- * 1) 如果子语句中有OR类型的子语句,则递归调用find_duplicate_ors,因为 子OR语句中
- * 或许也能提取公共项。
- * 2) 对AND操作进行拉平。
- */
- else if (and_clause((Node *) qual))
- {
- List *andlist = NIL;
- ListCell *temp;
- /* Recurse */
- /*
- * 子语句中存在一系列OR的情况。
- * 例如对于:
- * A=1 AND ((B=1 AND C=1) OR (B=1 AND D=1))
- * 这里的qual指针指向一个AND_EXPR类型的BoolExpr结构体,则
- *
- typedef struct BoolExpr
- {
- Expr xpr; = 略
- BoolExprType boolop; = AND_EXPR,即对下面的2个进行AND操作
- List *args; = 2个,分别是“A=1”和 “((B=1 AND C=1) OR (B=1 AND D=1))”
- } BoolExpr;
- *
- * 对于其中的“((B=1 AND C=1) OR (B=1 AND D=1))”,在递归调用中,
- * 会进入“分支一:or_clause”,进而转换为:
- * B=1 AND (C=1 OR D=1)
- *
- * 张大明白的blog:http://blog.csdn.net/shujiezhang
- */
- foreach(temp,((BoolExpr *) qual)->args)
- andlist = lappend(andlist,find_duplicate_ors(lfirst(temp)));
- /* Flatten any ANDs introduced just below here */
- /*
- * 拉平。
- *
- * 因为主语句是AND类型,子语句也是AND类型,所以可以直接把子语句拉到父节点。
- *
- */
- andlist = pull_ands(andlist);
- /* The AND list can't get shorter,so result is always an AND */
- return make_andclause(andlist);
- }
- else
- return qual;
- }