diff --git a/src/gausskernel/optimizer/prep/prepjointree.cpp b/src/gausskernel/optimizer/prep/prepjointree.cpp old mode 100755 new mode 100644 index 2187138e8..346739557 --- a/src/gausskernel/optimizer/prep/prepjointree.cpp +++ b/src/gausskernel/optimizer/prep/prepjointree.cpp @@ -127,35 +127,42 @@ static bool contains_swctes(const PlannerInfo *root); * Unlike most other functions in this file, this function doesn't recurse; * we rely on other processing to invoke it on sub-queries at suitable times. */ + /* +函数主要功能是在查询解析树中检查联接树是否为空,如果为空, +则创建一个特殊的范围表条目,然后将其添加到查询解析树的范围表中, +并在联接树中插入一个对这个新范围表条目的引用。这通常用于处理一些特殊情况, +以确保查询解析树的正确性。如果联接树已经非空或者在SET操作的顶层,就不做任何修改。 + */ void replace_empty_jointree(Query *parse) { - RangeTblEntry *rte; - Index rti; - RangeTblRef *rtr; + RangeTblEntry *rte; // 声明一个RangeTblEntry结构体指针,用于表示查询范围表条目 + Index rti; // 声明一个索引,用于表示范围表条目的索引 + RangeTblRef *rtr; // 声明一个RangeTblRef结构体指针,用于表示范围表引用 - /* Nothing to do if jointree is already nonempty */ + /* 如果联接树(jointree)已经不为空,就不需要做任何操作 */ if (parse->jointree->fromlist != NIL) return; - /* We mustn't change it in the top level of a setop tree, either */ + /* 如果在SET操作的顶层,我们也不能更改它 */ if (parse->setOperations) return; - /* Create suitable RTE */ - rte = makeNode(RangeTblEntry); - rte->rtekind = RTE_RESULT; - rte->eref = makeAlias("*RESULT*", NIL); + /* 创建适当的范围表条目(RangeTblEntry) */ + rte = makeNode(RangeTblEntry); // 创建一个新的范围表条目 + rte->rtekind = RTE_RESULT; // 设置范围表条目的类型为RTE_RESULT + rte->eref = makeAlias("*RESULT*", NIL); // 为范围表条目创建一个别名为"*RESULT*" - /* Add it to rangetable */ - parse->rtable = lappend(parse->rtable, rte); - rti = list_length(parse->rtable); + /* 将范围表条目添加到范围表中 */ + parse->rtable = lappend(parse->rtable, rte); // 将新创建的范围表条目添加到查询解析树的范围表中 + rti = list_length(parse->rtable); // 获取新添加的范围表条目的索引 - /* And jam a reference into the jointree */ - rtr = makeNode(RangeTblRef); - rtr->rtindex = rti; - parse->jointree->fromlist = list_make1(rtr); + /* 并且将一个范围表引用插入到联接树中 */ + rtr = makeNode(RangeTblRef); // 创建一个新的范围表引用 + rtr->rtindex = rti; // 设置范围表引用的索引为新添加的范围表条目的索引 + parse->jointree->fromlist = list_make1(rtr); // 将范围表引用添加到查询解析树的联接树中 } + #ifndef ENABLE_MULTIPLE_NODES /* * helper function to check if SWCB ctes contaisn in current SubQuery, normally help us to @@ -163,25 +170,29 @@ void replace_empty_jointree(Query *parse) */ static bool contains_swctes(const PlannerInfo *root) { + // 如果查询解析树为空或者其中的CTE列表为空,返回false if (root->parse == NULL || root->parse->cteList == NIL) { return false; } - List *cteList = root->parse->cteList; - ListCell *lc = NULL; - bool found = false; - foreach(lc, cteList) { - CommonTableExpr *cte = (CommonTableExpr *)lfirst(lc); + List *cteList = root->parse->cteList; // 获取查询解析树中的CTE列表 + ListCell *lc = NULL; // 声明一个用于遍历列表的列表元素指针 + bool found = false; // 声明一个布尔值,用于表示是否找到特定类型的CTE - /* check if cte from parse->ctelist is a swcb converted */ + // 遍历CTE列表 + foreach(lc, cteList) { + CommonTableExpr *cte = (CommonTableExpr *)lfirst(lc); // 获取当前CTE + + /* 检查parse->ctelist中的CTE是否是swcb转换的 */ if (cte->swoptions != NULL) { - found = true; - break; + found = true; // 如果CTE中包含swoptions,将found设置为true + break; // 跳出循环,因为已经找到了符合条件的CTE } } - return found; + return found; // 返回是否找到特定类型的CTE的结果 } + #endif /* @@ -277,35 +288,42 @@ void pull_up_sublinks(PlannerInfo* root) */ Node* assign_qual_clause(Node* new_node, Node* old_node, Node* qual, Relids old_node_relids) { + // 如果限定条件(qual)为空,则直接返回新节点(new_node),无需处理 if (qual == NULL) { return new_node; } + + // 从限定条件中获取相关的变量编号(varnos) Relids qual_varnos = pull_varnos(qual); + /* - * We need add this quals to new_node if old_node_relids can not include qual_varnos. - * than can happend when or_clause pull up. + * 如果限定条件中的变量编号(qual_varnos)不能完全包含在旧节点的关系标识集合(old_node_relids)中, + * 则需要将限定条件添加到新节点(new_node)中。 + * 这种情况可能会发生在OR条件的上升处理中。 */ if (!bms_is_subset(qual_varnos, old_node_relids)) { if (IsA(new_node, FromExpr)) { - ((FromExpr*)new_node)->quals = qual; + ((FromExpr*)new_node)->quals = qual; // 将限定条件设置为新节点的条件 } else { - new_node = (Node*)makeFromExpr(list_make1(new_node), qual); + new_node = (Node*)makeFromExpr(list_make1(new_node), qual); // 创建一个新的FromExpr节点,并将限定条件添加到其中 } } - /* Only need put qual to old node, this qual can be original(pull up before) qual.*/ + /* 否则,只需要将限定条件放在旧节点上,这个限定条件可能是原始的(在上升之前已经存在的)限定条件。 */ else { if (IsA(old_node, FromExpr)) { - ((FromExpr*)old_node)->quals = qual; + ((FromExpr*)old_node)->quals = qual; // 将限定条件设置为旧节点的条件 } else { - ((JoinExpr*)old_node)->quals = qual; + ((JoinExpr*)old_node)->quals = qual; // 将限定条件设置为联接节点的条件 } } + // 释放变量编号集合的内存 bms_free_ext(qual_varnos); - return new_node; + return new_node; // 返回处理后的新节点 } + /* * Recurse through jointree nodes for pull_up_sublinks() * @@ -506,12 +524,12 @@ static Node* pull_up_sublinks_jointree_recurse(PlannerInfo* root, Node* jtnode, static Node* pull_up_sublinks_qual_recurse(PlannerInfo* root, Node* node, Node** jtlink1, Relids *available_rels1, Node** jtlink2, Relids *available_rels2, Node* all_quals) { - if (node == NULL) + if (node == NULL)// 如果传入的节点为空,直接返回NULL return NULL; - if (IsA(node, SubLink)) { - SubLink* sublink = (SubLink*)node; - JoinExpr* j = NULL; - Relids child_rels; + if (IsA(node, SubLink)) {// 如果节点是一个子查询(SubLink) + SubLink* sublink = (SubLink*)node;// 将节点转换为子查询结构体 + JoinExpr* j = NULL;// 声明一个JoinExpr结构体指针,用于表示连接表达式 + Relids child_rels;// 用于存储子查询关联的关系标识集合 if (has_no_expand_hint((Query*)sublink->subselect)) { return node; @@ -685,12 +703,13 @@ static Node* pull_up_sublinks_qual_recurse(PlannerInfo* root, Node* node, Node** ListCell* l = NULL; foreach (l, ((BoolExpr*)node)->args) { - Node* oldclause = (Node*)lfirst(l); - Node* newclause = NULL; - + Node* oldclause = (Node*)lfirst(l);// 获取当前参数作为旧的子句 + Node* newclause = NULL;// 用于存储处理后的新子句 + // 调用递归函数处理当前子句 newclause = pull_up_sublinks_qual_recurse( root, oldclause, jtlink1, available_rels1, jtlink2, available_rels2, all_quals); - if (newclause != NULL) + // 如果处理后的新子句不为空 + if (newclause != NULL)// 将新子句添加到新子句列表中 newclauses = lappend(newclauses, newclause); } /* We might have got back fewer clauses than we started with */ @@ -834,29 +853,34 @@ static Node* pull_up_sublinks_targetlist(PlannerInfo *root, */ void inline_set_returning_functions(PlannerInfo* root) { - ListCell* rt = NULL; + ListCell* rt = NULL; // 声明一个用于遍历查询的范围表条目的列表元素指针 + // 遍历查询解析树的范围表条目 foreach (rt, root->parse->rtable) { - RangeTblEntry* rte = (RangeTblEntry*)lfirst(rt); + RangeTblEntry* rte = (RangeTblEntry*)lfirst(rt); // 获取当前范围表条目 + // 如果范围表条目的类型是函数(RTE_FUNCTION) if (rte->rtekind == RTE_FUNCTION) { - Query* funcquery = NULL; + Query* funcquery = NULL; // 用于存储函数展开后的查询 - /* Check safety of expansion, and expand if possible */ + /* 检查展开的安全性,并在可能的情况下进行展开 */ funcquery = inline_set_returning_function(root, rte); + + // 如果成功展开函数 if (funcquery != NULL) { - /* Successful expansion, replace the rtable entry */ + /* 成功展开,替换范围表条目的类型为子查询(RTE_SUBQUERY) */ rte->rtekind = RTE_SUBQUERY; - rte->subquery = funcquery; - rte->funcexpr = NULL; - rte->funccoltypes = NIL; - rte->funccoltypmods = NIL; - rte->funccolcollations = NIL; + rte->subquery = funcquery; // 将展开后的查询存储在范围表条目中 + rte->funcexpr = NULL; // 清空函数表达式 + rte->funccoltypes = NIL; // 清空函数列类型列表 + rte->funccoltypmods = NIL; // 清空函数列类型修改列表 + rte->funccolcollations = NIL; // 清空函数列的字符集列表 } } } } + /* * This recursively processes the jointree and returns a modified jointree. */ @@ -1530,18 +1554,20 @@ static Node* pull_up_simple_union_all(PlannerInfo* root, Node* jtnode, RangeTblE static void pull_up_union_leaf_queries( Node* setOp, PlannerInfo* root, int parentRTindex, Query* setOpQuery, int childRToffset) { + // 如果 setOp 是 RangeTblRef 类型 if (IsA(setOp, RangeTblRef)) { - RangeTblRef* rtr = (RangeTblRef*)setOp; + RangeTblRef* rtr = (RangeTblRef*)setOp; // 将 setOp 转换为 RangeTblRef 结构体 + int childRTindex; AppendRelInfo* appinfo = NULL; /* - * Calculate the index in the parent's range table + * 计算子查询在父查询范围表中的索引 */ childRTindex = childRToffset + rtr->rtindex; /* - * Build a suitable AppendRelInfo, and attach to parent's list. + * 创建适当的 AppendRelInfo 结构体,并附加到父查询的列表中 */ appinfo = makeNode(AppendRelInfo); appinfo->parent_relid = parentRTindex; @@ -1553,29 +1579,35 @@ static void pull_up_union_leaf_queries( root->append_rel_list = lappend(root->append_rel_list, appinfo); /* - * Recursively apply pull_up_subqueries to the new child RTE. (We - * must build the AppendRelInfo first, because this will modify it.) - * Note that we can pass NULL for containing-join info even if we're - * actually under an outer join, because the child's expressions - * aren't going to propagate up above the join. + * 递归应用 pull_up_subqueries_recurse 函数到新的子查询 RTE。 + * 需要先构建 AppendRelInfo,因为这将会修改它。 + * 注意,即使我们实际上处于外连接下,也可以传递 NULL 作为包含连接信息, + * 因为子查询的表达式不会向上传播到连接之上。 */ rtr = makeNode(RangeTblRef); rtr->rtindex = childRTindex; (void)pull_up_subqueries_recurse(root, (Node*)rtr, NULL, NULL, appinfo); - } else if (IsA(setOp, SetOperationStmt)) { + } + // 如果 setOp 是 SetOperationStmt 类型 + else if (IsA(setOp, SetOperationStmt)) { SetOperationStmt* op = (SetOperationStmt*)setOp; - /* Recurse to reach leaf queries */ + /* 递归处理左子查询 */ pull_up_union_leaf_queries(op->larg, root, parentRTindex, setOpQuery, childRToffset); + + /* 递归处理右子查询 */ pull_up_union_leaf_queries(op->rarg, root, parentRTindex, setOpQuery, childRToffset); - } else { + } + // 如果 setOp 是未知的节点类型 + else { ereport(ERROR, (errmodule(MOD_OPT), errcode(ERRCODE_UNRECOGNIZED_NODE_TYPE), - errmsg("unrecognized node type: %d", (int)nodeTag(setOp)))); + errmsg("未知的节点类型: %d", (int)nodeTag(setOp)))); } } + /* * make_setop_translation_list * Build the list of translations from parent Vars to child Vars for @@ -1585,21 +1617,26 @@ static void pull_up_union_leaf_queries( */ static void make_setop_translation_list(Query* query, Index newvarno, List** translated_vars) { - List* vars = NIL; - ListCell* l = NULL; + List* vars = NIL; // 声明一个用于存储变量的列表 + ListCell* l = NULL; // 声明一个用于遍历目标列表的列表元素指针 + // 遍历查询的目标列表 foreach (l, query->targetList) { - TargetEntry* tle = (TargetEntry*)lfirst(l); + TargetEntry* tle = (TargetEntry*)lfirst(l); // 获取当前目标条目 + // 如果目标条目被标记为 "resjunk",则跳过它,不处理 if (tle->resjunk) continue; + // 创建一个新的变量,表示目标条目,并将其添加到变量列表中 vars = lappend(vars, makeVarFromTargetEntry(newvarno, tle)); } + // 将构建的变量列表赋值给传入的 translated_vars 指针 *translated_vars = vars; } + /* * is_simple_lateral_subquery * If the subquery is LATERAL, check for pullup restrictions from that. @@ -1660,7 +1697,7 @@ static bool is_simple_lateral_subquery(Query* subquery, JoinExpr *lowest_outer_j static bool is_grouping_subquery(Query* subquery) { - /* + /* * Can't pull up a subquery involving grouping, aggregation, sorting, * limiting, or WITH. (XXX WITH could possibly be allowed later) * @@ -1670,14 +1707,20 @@ static bool is_grouping_subquery(Query* subquery) * that case the locking was originally declared in the upper query * anyway. */ + // 如果子查询中包含聚合函数(hasAggs)、窗口函数(hasWindowFuncs)、GROUP BY 子句(groupClause)、 + // GROUPING SETS 子句(groupingSets)、HAVING 子句(havingQual)、排序子句(sortClause)、 + // DISTINCT 子句(distinctClause)、LIMIT 偏移(limitOffset)、LIMIT 计数(limitCount)、 + // FOR UPDATE 子句(hasForUpdate)或者通用表达式列表(cteList),则认为它不是分组子查询。 if (subquery->hasAggs || subquery->hasWindowFuncs || subquery->groupClause || subquery->groupingSets || subquery->havingQual || subquery->sortClause || subquery->distinctClause || subquery->limitOffset || subquery->limitCount || subquery->hasForUpdate || subquery->cteList) return false; + // 如果上述条件都不满足,则认为子查询是分组子查询。 return true; } + /* * is_simple_subquery * Check a subquery in the range table to see if it's simple enough @@ -1788,64 +1831,72 @@ static bool is_simple_union_all(Query* subquery) { SetOperationStmt* topop = NULL; - /* Let's just make sure it's a valid subselect ... */ + /* 首先确保子查询是一个有效的子查询... */ if (!IsA(subquery, Query) || subquery->commandType != CMD_SELECT || subquery->utilityStmt != NULL) ereport( - ERROR, (errmodule(MOD_OPT), errcode(ERRCODE_OPTIMIZER_INCONSISTENT_STATE), (errmsg("subquery is bogus")))); + ERROR, (errmodule(MOD_OPT), errcode(ERRCODE_OPTIMIZER_INCONSISTENT_STATE), (errmsg("子查询无效")))); - /* Is it a set-operation query at all? */ + /* 子查询是否是一个集合操作查询? */ topop = (SetOperationStmt*)subquery->setOperations; if (topop == NULL) return false; AssertEreport( - IsA(topop, SetOperationStmt), MOD_OPT_REWRITE, "subquery's setOperations mismatch in is_simple_union_all"); + IsA(topop, SetOperationStmt), MOD_OPT_REWRITE, "is_simple_union_all 中子查询的 setOperations 不匹配"); #ifndef ENABLE_MULTIPLE_NODES + // 如果子查询包含 ROWNUM 过滤条件,就不是简单的 UNION ALL 查询 if (ContainRownumQual(subquery)) { return false; } #endif - /* Can't handle ORDER BY, LIMIT/OFFSET, locking, or WITH */ + /* 不能处理包含 ORDER BY、LIMIT/OFFSET、锁定或 WITH 子句的子查询 */ if (subquery->sortClause || subquery->limitOffset || subquery->limitCount || subquery->rowMarks || subquery->cteList) return false; - /* Recursively check the tree of set operations */ + /* 递归检查集合操作树 */ return is_simple_union_all_recurse((Node*)topop, subquery, topop->colTypes); } + static bool is_simple_union_all_recurse(Node* setOp, Query* setOpQuery, List* colTypes) { + // 如果当前节点是 RangeTblRef 类型 if (IsA(setOp, RangeTblRef)) { - RangeTblRef* rtr = (RangeTblRef*)setOp; - RangeTblEntry* rte = rt_fetch(rtr->rtindex, setOpQuery->rtable); - Query* subquery = rte->subquery; + RangeTblRef* rtr = (RangeTblRef*)setOp; // 将当前节点转换为 RangeTblRef 结构体 + RangeTblEntry* rte = rt_fetch(rtr->rtindex, setOpQuery->rtable); // 获取当前节点对应的范围表条目 + Query* subquery = rte->subquery; // 获取范围表条目中的子查询 - AssertEreport(subquery != NULL, MOD_OPT_REWRITE, "subquery should not be NULL in is_simple_union_all_recurse"); + AssertEreport(subquery != NULL, MOD_OPT_REWRITE, "is_simple_union_all_recurse 中的子查询不应为 NULL"); - /* Leaf nodes are OK if they match the toplevel column types */ - /* We don't have to compare typmods or collations here */ + /* 如果是叶子节点,需要检查其列类型是否与顶层查询的列类型匹配 */ + /* 我们不必在这里比较类型修饰符(typmods)或字符集(collations) */ return tlist_same_datatypes(subquery->targetList, colTypes, true); - } else if (IsA(setOp, SetOperationStmt)) { - SetOperationStmt* op = (SetOperationStmt*)setOp; + } + // 如果当前节点是 SetOperationStmt 类型 + else if (IsA(setOp, SetOperationStmt)) { + SetOperationStmt* op = (SetOperationStmt*)setOp; // 将当前节点转换为 SetOperationStmt 结构体 - /* Must be UNION ALL */ + /* 必须是 UNION ALL 操作 */ if (op->op != SETOP_UNION || !op->all) return false; - /* Recurse to check inputs */ + /* 递归检查左子树和右子树 */ return is_simple_union_all_recurse(op->larg, setOpQuery, colTypes) && is_simple_union_all_recurse(op->rarg, setOpQuery, colTypes); - } else { + } + // 如果当前节点是未知的节点类型 + else { ereport(ERROR, (errmodule(MOD_OPT), errcode(ERRCODE_UNRECOGNIZED_NODE_TYPE), - errmsg("unrecognized node type: %d", (int)nodeTag(setOp)))); - return false; /* keep compiler quiet */ + errmsg("未知的节点类型: %d", (int)nodeTag(setOp)))); + return false; /* 使编译器保持安静 */ } } + /* * is_safe_append_member * Check a subquery that is a leaf of a UNION ALL appendrel to see if it's @@ -1897,34 +1948,33 @@ jointree_contains_lateral_outer_refs(Node *jtnode, bool restricted, if (jtnode == NULL) return false; if (IsA(jtnode, RangeTblRef)) - return false; + return false; // 如果当前节点是范围表引用节点,不包含外部引用,返回 false else if (IsA(jtnode, FromExpr)) { FromExpr *f = (FromExpr *) jtnode; ListCell *l = NULL; - /* First, recurse to check child joins */ + /* 首先递归检查子联接 */ foreach(l, f->fromlist) { if (jointree_contains_lateral_outer_refs((Node *)lfirst(l), restricted, safe_upper_varnos)) - return true; + return true; // 如果子联接包含外部引用,返回 true } - /* Then check the top-level quals */ + /* 然后检查顶层条件表达式 */ if (restricted && !bms_is_subset(pull_varnos_of_level(f->quals, 1), safe_upper_varnos)) - return true; + return true; // 如果条件表达式中包含外部引用,且不在安全的上级变量范围内,返回 true } else if (IsA(jtnode, JoinExpr)) { JoinExpr *j = (JoinExpr *) jtnode; /* - * If this is an outer join, we mustn't allow any upper lateral - * references in or below it. + * 如果这是一个外连接,我们不能允许在其内部或下方有任何上级的外部引用。 */ if (j->jointype != JOIN_INNER) { @@ -1932,28 +1982,29 @@ jointree_contains_lateral_outer_refs(Node *jtnode, bool restricted, safe_upper_varnos = NULL; } - /* Check the child joins */ + /* 检查子联接 */ if (jointree_contains_lateral_outer_refs(j->larg, restricted, safe_upper_varnos)) - return true; + return true; // 如果左子联接包含外部引用,返回 true if (jointree_contains_lateral_outer_refs(j->rarg, restricted, safe_upper_varnos)) - return true; + return true; // 如果右子联接包含外部引用,返回 true - /* Check the JOIN's qual clauses */ + /* 检查联接的条件表达式 */ if (restricted && !bms_is_subset(pull_varnos_of_level(j->quals, 1), safe_upper_varnos)) - return true; + return true; // 如果条件表达式中包含外部引用,且不在安全的上级变量范围内,返回 true } else - elog(ERROR, "unrecognized node type: %d", + elog(ERROR, "未识别的节点类型: %d", (int) nodeTag(jtnode)); return false; } + /* * Helper routine for pull_up_subqueries: do pullup_replace_vars on every * expression in the jointree, without changing the jointree structure itself. @@ -2057,10 +2108,20 @@ static void replace_vars_in_jointree(Node* jtnode, pullup_replace_vars_context* */ static Node* pullup_replace_vars(Node* expr, pullup_replace_vars_context* context) { + // 使用 replace_rte_variables 函数替换表达式中的变量 + // 参数说明: + // expr:待替换的表达式 + // context->varno:用于替换的范围表索引 + // 0:替换的层级深度(0 表示替换所有层级) + // pullup_replace_vars_callback:用于处理替换的回调函数 + // (void*)context:回调函数的上下文数据 + // context->outer_hasSubLinks:是否包含子查询链接在外部查询中 + return replace_rte_variables( expr, context->varno, 0, pullup_replace_vars_callback, (void*)context, context->outer_hasSubLinks); } + static Node* pullup_replace_vars_callback(Var* var, replace_rte_variables_context* context) { pullup_replace_vars_context* rcon = (pullup_replace_vars_context*)context->callback_arg; @@ -2220,7 +2281,18 @@ static Query * pullup_replace_vars_subquery(Query *query, pullup_replace_vars_context *context) { + // 确保输入的 query 是一个有效的 Query 结构 Assert(IsA(query, Query)); + + // 使用 replace_rte_variables 函数替换子查询中的变量 + // 参数说明: + // (Node *) query:待替换的子查询 + // context->varno:用于替换的范围表索引 + // 1:替换的层级深度(1 表示只替换一层,即子查询中的变量) + // pullup_replace_vars_callback:用于处理替换的回调函数 + // (void *) context:回调函数的上下文数据 + // NULL:不包含子查询链接在外部查询中 + return (Query *) replace_rte_variables((Node *) query, context->varno, 1, pullup_replace_vars_callback, @@ -2228,6 +2300,7 @@ pullup_replace_vars_subquery(Query *query, NULL); } + /* * flatten_simple_union_all * Try to optimize top-level UNION ALL structure into an appendrel