From 44f750e0188c6101a8901fa6e9fa85d22bb0c3b2 Mon Sep 17 00:00:00 2001 From: ljh0804 Date: Thu, 10 Aug 2023 21:14:09 +0800 Subject: [PATCH] Update execCurrent.cpp --- .../runtime/executor/execCurrent.cpp | 97 ++++++++----------- 1 file changed, 41 insertions(+), 56 deletions(-) diff --git a/src/gausskernel/runtime/executor/execCurrent.cpp b/src/gausskernel/runtime/executor/execCurrent.cpp index 9e49bdc14..e44e7c0cf 100644 --- a/src/gausskernel/runtime/executor/execCurrent.cpp +++ b/src/gausskernel/runtime/executor/execCurrent.cpp @@ -1,13 +1,13 @@ /* ------------------------------------------------------------------------- * * execCurrent.c - * executor support for WHERE CURRENT OF cursor + * 执行程序支持WHERE CURRENT OF游标执行程序支持WHERE CURRENT OF游标 * - * Portions Copyright (c) 2020 Huawei Technologies Co.,Ltd. - * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California + * 华为技术有限公司版权所有 + * 部分版权所有(c) 1996-2012, PostgreSQL全球发展集团 + * 版权所有(c) 1994,加州大学董事会 * - * IDENTIFICATION + * 识别 * src/backend/executor/execCurrent.c * * ------------------------------------------------------------------------- @@ -38,14 +38,12 @@ static ScanState* search_plan_tree(PlanState *node, Oid table_oid); /* * execCurrentOf * - * Given a CURRENT OF expression and the OID of a table, determine which row - * of the table is currently being scanned by the cursor named by CURRENT OF, - * and return the row's TID into *current_tid. + * 给定CURRENT OF表达式和表的OID,确定哪一行 + * 当前正在被名为CURRENT of的游标扫描 + * 并返回该行的TID为*current_tid。 * - * Returns TRUE if a row was identified. Returns FALSE if the cursor is valid - * for the table but is not currently scanning a row of the table (this is a - * legal situation in inheritance cases). Raises error if cursor is not a - * valid updatable scan of the specified table. + * 如果一行被识别,则返回TRUE。如果游标有效,则返回FALSE + * 但是当前没有扫描表的一行(这是继承情况下的合法情况)。如果游标不是指定表的有效可更新扫描,则引发错误。 */ bool execCurrentOf(CurrentOfExpr *cexpr, ExprContext *econtext, Relation relation, ItemPointer current_tid, RelationPtr partitionOfCursor_tid) @@ -55,14 +53,14 @@ bool execCurrentOf(CurrentOfExpr *cexpr, ExprContext *econtext, Relation relatio QueryDesc *query_desc = NULL; Oid table_oid = RelationGetRelid(relation); - /* Get the cursor name --- may have to look up a parameter reference */ + /* 获取游标名称——可能需要查找参数引用 */ if (cexpr->cursor_name) { cursor_name = cexpr->cursor_name; } else { cursor_name = fetch_cursor_param_value(econtext, cexpr->cursor_param); } - /* Find the cursor's portal */ + /* 找到游标的入口 */ portal = GetPortalByName(cursor_name); if (!PortalIsValid(portal)) { ereport(ERROR, (errcode(ERRCODE_UNDEFINED_CURSOR), @@ -70,8 +68,7 @@ bool execCurrentOf(CurrentOfExpr *cexpr, ExprContext *econtext, Relation relatio } /* - * We have to watch out for non-SELECT queries as well as held cursors, - * both of which may have null query_desc. + * 我们必须注意非select查询和持有的游标,它们的query_desc都可能为空 */ if (portal->strategy != PORTAL_ONE_SELECT) { ereport(ERROR, @@ -85,26 +82,23 @@ bool execCurrentOf(CurrentOfExpr *cexpr, ExprContext *econtext, Relation relatio } /* - * We have two different strategies depending on whether the cursor uses - * FOR UPDATE/SHARE or not. The reason for supporting both is that the - * FOR UPDATE code is able to identify a target table in many cases where - * the other code can't, while the non-FOR-UPDATE case allows use of WHERE - * CURRENT OF with an insensitive cursor. + * 根据游标是否使用,我们有两种不同的策略 + * 是否更新/共享。支持两者的原因是 + * 在许多情况下,FOR UPDATE代码能够识别目标表,而其他代码不能,而非FOR-UPDATE情况允许使用不敏感游标的when CURRENT of。 */ if (query_desc->estate->es_rowMarks) { ExecRowMark *erm = NULL; ListCell *lc = NULL; /* - * Here, the query must have exactly one FOR UPDATE/SHARE reference to - * the target table, and we dig the ctid info out of that. + * 这里,查询必须只有一个对目标表的FOR UPDATE/SHARE引用,我们从中挖掘出ctid信息。 */ erm = NULL; foreach (lc, query_desc->estate->es_rowMarks) { ExecRowMark *thiserm = (ExecRowMark *)lfirst(lc); if (!RowMarkRequiresRowShareLock(thiserm->markType)) { - continue; /* ignore non-FOR UPDATE/SHARE items */ + continue; /* 忽略非for UPDATE/SHARE项 */ } if (RelationGetRelid(thiserm->relation) == table_oid) { @@ -124,15 +118,14 @@ bool execCurrentOf(CurrentOfExpr *cexpr, ExprContext *econtext, Relation relatio } /* - * The cursor must have a current result row: per the SQL spec, it's - * an error if not. + * 游标必须有当前结果行:根据SQL规范,如果没有,则会出现错误。 */ if (portal->atStart || portal->atEnd) { ereport(ERROR, (errcode(ERRCODE_INVALID_CURSOR_STATE), errmsg("cursor \"%s\" is not positioned on a row when the cursor uses for UPDATE/SHARE", cursor_name))); } - /* Return the currently scanned TID, if there is one */ + /* 返回当前扫描的TID(如果有) */ if (ItemPointerIsValid(&(erm->curCtid))) { *current_tid = erm->curCtid; @@ -144,9 +137,7 @@ bool execCurrentOf(CurrentOfExpr *cexpr, ExprContext *econtext, Relation relatio } /* - * This table didn't produce the cursor's current row; some other - * inheritance child of the same parent must have. Signal caller to - * do nothing on this table. + * 这个表没有产生游标的当前行;必须有同一父节点的其他继承子节点。信号调用者在表上什么都不做。 */ return false; } else { @@ -156,9 +147,7 @@ bool execCurrentOf(CurrentOfExpr *cexpr, ExprContext *econtext, Relation relatio ItemPointer tuple_tid; /* - * Without FOR UPDATE, we dig through the cursor's plan to find the - * scan node. Fail if it's not there or buried underneath - * aggregation. + * 如果没有FOR UPDATE,我们将通过游标的计划来查找扫描节点。如果不存在或隐藏在聚合下面,则失败。 */ scanstate = search_plan_tree(query_desc->planstate, table_oid); if (scanstate == NULL) { @@ -168,23 +157,21 @@ bool execCurrentOf(CurrentOfExpr *cexpr, ExprContext *econtext, Relation relatio } /* - * The cursor must have a current result row: per the SQL spec, it's - * an error if not. We test this at the top level, rather than at the - * scan node level, because in inheritance cases any one table scan - * could easily not be on a row. We want to return false, not raise - * error, if the passed-in table OID is for one of the inactive scans. + * 游标必须有当前结果行:根据SQL规范,如果没有,则会出现错误。 + * 我们在顶层测试,而不是在扫描节点级测试,因为在继承情况下,任何一个表扫描都很容易不在一行上。 + * 如果传入的表OID是用于非活动扫描的,我们希望返回false,而不是引发错误。 */ if (portal->atStart || portal->atEnd) { ereport(ERROR, (errcode(ERRCODE_INVALID_CURSOR_STATE), errmsg( "cursor \"%s\" is not positioned on a row when the cursor doesn't use for UPDATE/SHARE", cursor_name))); } - /* Now OK to return false if we found an inactive scan */ + /* 现在OK返回false如果我们发现一个非活动扫描 */ if (TupIsNull(scanstate->ss_ScanTupleSlot)) { return false; } - /* Use slot_getattr to catch any possible mistakes */ + /* 使用slot_getattr捕获任何可能的错误 */ tuple_tableoid = DatumGetObjectId(tableam_tslot_getattr(scanstate->ss_ScanTupleSlot, TableOidAttributeNumber, &lisnull)); Assert(!lisnull); tuple_tid = (ItemPointer)DatumGetPointer( @@ -206,7 +193,7 @@ bool execCurrentOf(CurrentOfExpr *cexpr, ExprContext *econtext, Relation relatio /* * fetch_cursor_param_value * - * Fetch the string value of a param, verifying it is of type REFCURSOR. + * 获取参数的字符串值,验证它是REFCURSOR类型。. */ static char *fetch_cursor_param_value(ExprContext *econtext, int paramId) { @@ -215,20 +202,20 @@ static char *fetch_cursor_param_value(ExprContext *econtext, int paramId) if (paramInfo && paramId > 0 && paramId <= paramInfo->numParams) { ParamExternData *prm = ¶mInfo->params[paramId - 1]; - /* give hook a chance in case parameter is dynamic */ + /* 如果参数是动态的,给钩子一个机会 */ if (!OidIsValid(prm->ptype) && paramInfo->paramFetch != NULL) { (*paramInfo->paramFetch)(paramInfo, paramId); } if (OidIsValid(prm->ptype) && !prm->isnull) { - /* safety check in case hook did something unexpected */ + /* 安全检查,以防钩子发生意外 */ if (prm->ptype != REFCURSOROID) { ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("type of parameter %d (%s) does not match that when preparing the plan (%s)", paramId, format_type_be(prm->ptype), format_type_be(REFCURSOROID)))); } - /* We know that refcursor uses text's I/O routines */ + /* 我们知道refcursor使用text的I/O例程 */ return TextDatumGetCString(prm->value); } } @@ -240,8 +227,8 @@ static char *fetch_cursor_param_value(ExprContext *econtext, int paramId) /* * search_plan_tree * - * Search through a PlanState tree for a scan node on the specified table. - * Return NULL if not found or multiple candidates. + * 在PlanState树中搜索指定表上的扫描节点。 + * 如果没有找到或有多个候选,则返回NULL。 */ #ifdef PGXC ScanState* search_plan_tree(PlanState* node, Oid table_oid) @@ -262,7 +249,7 @@ static ScanState* search_plan_tree(PlanState* node, Oid table_oid) } #endif /* - * scan nodes can all be treated alike + * 扫描节点都可以被同等对待 */ case T_SeqScanState: case T_IndexScanState: @@ -284,8 +271,7 @@ static ScanState* search_plan_tree(PlanState* node, Oid table_oid) return result; } /* - * For Append, we must look through the members; watch out for - * multiple matches (possible if it was from UNION ALL) + * 对于Append,必须遍历成员;注意多个匹配(可能来自UNION ALL) */ case T_AppendState: { AppendState *astate = (AppendState *)node; @@ -297,14 +283,14 @@ static ScanState* search_plan_tree(PlanState* node, Oid table_oid) if (elem == NULL) continue; if (result != NULL) - return NULL; /* multiple matches */ + return NULL; /* 多个匹配 */ result = elem; } return result; } /* - * Similarly for MergeAppend + * 类似于MergeAppend */ case T_MergeAppendState: { MergeAppendState *mstate = (MergeAppendState *)node; @@ -318,15 +304,14 @@ static ScanState* search_plan_tree(PlanState* node, Oid table_oid) continue; } if (result != NULL) { - return NULL; /* multiple matches */ + return NULL; /* 多个匹配 */ } result = elem; } return result; } /* - * Result and Limit can be descended through (these are safe - * because they always return their input's current row) + * Result和Limit可以依次下降(它们是安全的,因为它们总是返回输入的当前行) */ #ifdef PGXC case T_MaterialState: @@ -337,13 +322,13 @@ static ScanState* search_plan_tree(PlanState* node, Oid table_oid) return search_plan_tree(node->lefttree, table_oid); /* - * SubqueryScan too, but it keeps the child in a different place + * SubqueryScan也可以,但它将子对象保存在不同的位置 */ case T_SubqueryScanState: return search_plan_tree(((SubqueryScanState *)node)->subplan, table_oid); default: - /* Otherwise, assume we can't descend through it */ + /* 否则,假设我们不能从里面下去 */ break; } return NULL;