forked from huawei/openGauss-server
Update execCurrent.cpp
This commit is contained in:
parent
7758348b68
commit
1a882a9ee6
|
|
@ -47,6 +47,63 @@ static ScanState* search_plan_tree(PlanState *node, Oid table_oid);
|
|||
* legal situation in inheritance cases). Raises error if cursor is not a
|
||||
* valid updatable scan of the specified table.
|
||||
*/
|
||||
/*The segment code defines a function named execCurrentOf, which is used to execute the CURRENT OF expression in SQL query.
|
||||
The CURRENT OF expression is a part of SQL/PSM (Persistent Storage Module),
|
||||
which is used to implement sensitive operations on a cursor.
|
||||
The function execCurrentOf receives five parameters:
|
||||
|
||||
1. cexpr: a pointer to the CurrentOfExpr structure, which contains the information of the CURRENT OF expression.
|
||||
2. econtext: a pointer to ExprContext structure, which contains the context information of expression execution.
|
||||
3. Relationship: A pointer to the relationship structure, which represents a relationship (i.e. a table) in the database.
|
||||
4. current_tid: a pointer to the ItemPointer structure, which represents the current transaction ID.
|
||||
5. partitionOfCursor_tid: A pointer to the RelationPtr structure, which represents the partition of the cursor.
|
||||
|
||||
The function first obtains the name of the cursor according to cexpr, and
|
||||
then finds the corresponding Portal according to the name.
|
||||
If a valid Portal cannot be found, an error is reported. Then, the function checks
|
||||
the query description (query_desc) corresponding to the Portal.
|
||||
An error is also reported if the query description does not exist
|
||||
or the status of the query description is invalid.
|
||||
|
||||
Then, the function decides which strategy to execute according to the row marks in the query description.
|
||||
If there is a line mark, use FOR UPDATE/SHARE; Otherwise, use a FOR-UPDATE method.
|
||||
|
||||
It defines a variable named `erm` with an initial value of NULL. Then it traverses ` query _ desc-> estate-> es _ row marks`,
|
||||
which is a list of all the rowmarks in the cursor query. During traversal, it
|
||||
checks whether each row tag needs a row share lock, and if not, it ignores the row tag.
|
||||
|
||||
For the row tag that needs a row sharing lock, the code checks whether the table associated with the row tag is
|
||||
the target table (that is, the OID returned by the RelationGetRelid' of `thiserm-> relation' is equal to table_oid').
|
||||
If it is, and there is already a row tag associated with the target table, it will report an error because
|
||||
the cursor cannot have more than one FOR UPDATE/SHARE reference to the same table.
|
||||
|
||||
After the traversal is completed, if the row tag associated with the target table is not found, it will report an error,
|
||||
because the cursor must have a FOR UPDATE/SHARE reference to the target table.
|
||||
|
||||
Next, the code checks whether the cursor currently has a result row.
|
||||
If not, it will report an error, because in the SQL specification, this is wrong.
|
||||
|
||||
Finally, if there is a valid TID (transaction ID) of the current scan, it will set' current_tid' and check whether
|
||||
the relationship is partitioned. If the relationship is partitioned, it will set `partition of cursor _ tid' to NULL.
|
||||
Then return true, indicating that the related TID has been found. If a valid TID is not found, it will return false,
|
||||
indicating that this table has not generated the current row of the cursor, and other inherited
|
||||
sub-tables may have generated the current row of the cursor.
|
||||
|
||||
Some variables are defined, including a pointer named scanstate', a boolean variable` lisnull',
|
||||
an Oid variable` tuple_tableoid' and an ItemPointer variable` tuple_tid'.
|
||||
|
||||
Then, it searches the search_plan_tree by calling the `search _ plan _ tree` function to find the scan node
|
||||
associated with the given table OID. If the scan node is not found,
|
||||
or the scan node is overwritten by the aggregation operation, it will report an error.
|
||||
|
||||
Next, the code checks whether the cursor currently has a result row. If not,
|
||||
it will report an error, because in the SQL specification, this is wrong.
|
||||
|
||||
Then, if the current scan tuple in the scan state is NULL, it will return false.
|
||||
|
||||
Finally, the code uses the slot_getattr function to get the table OID and transaction ID of
|
||||
the tuple and check whether they are valid. If the relationship is partitioned, it will also check
|
||||
whether the table OID is the same as the parent table OID of the partition.*/
|
||||
bool execCurrentOf(CurrentOfExpr *cexpr, ExprContext *econtext, Relation relation, ItemPointer current_tid,
|
||||
RelationPtr partitionOfCursor_tid)
|
||||
{
|
||||
|
|
@ -208,6 +265,22 @@ bool execCurrentOf(CurrentOfExpr *cexpr, ExprContext *econtext, Relation relatio
|
|||
*
|
||||
* Fetch the string value of a param, verifying it is of type REFCURSOR.
|
||||
*/
|
||||
/*This code defines a function `fetch _ cursor _ param _ value`, which is used to get the specified
|
||||
parameter value, especially when the parameter is of the reference cursor type.
|
||||
|
||||
The input parameters of the function include a pointer to an ExprContext structure and an integer paramId.
|
||||
The ExprContext' structure contains the execution context of the expression, which may contain
|
||||
some parameter information. ParamId' is the ID of the parameter to get.
|
||||
|
||||
The function first checks whether there is parameter information and whether the parameter ID is within the valid range.
|
||||
Then, it locates the specific parameter and checks its type. If the parameter type is dynamic (that is, its type identifier is invalid)
|
||||
and there is a parameter obtaining function, it will call this function to obtain the value of the parameter.
|
||||
|
||||
If the parameter type is valid and not null, the function will check further. If the parameter type is not a reference refcursor,
|
||||
it will report an error because the function only deals with this type. If the parameter type is a reference cursor,
|
||||
the function will convert its value to a C string and return this string.
|
||||
|
||||
If the value of the parameter is not found during the execution of the function, it will report an error and return NULL.*/
|
||||
static char *fetch_cursor_param_value(ExprContext *econtext, int paramId)
|
||||
{
|
||||
ParamListInfo paramInfo = econtext->ecxt_param_list_info;
|
||||
|
|
@ -243,6 +316,40 @@ static char *fetch_cursor_param_value(ExprContext *econtext, int paramId)
|
|||
* Search through a PlanState tree for a scan node on the specified table.
|
||||
* Return NULL if not found or multiple candidates.
|
||||
*/
|
||||
/*t searches the PlanState tree for scan nodes on the specified table.
|
||||
In PostgreSQL, the PlanState tree is a data structure representing the query execution plan.
|
||||
The function `search _ plan _ tree` receives two parameters: a pointer` node of PlanState and
|
||||
a ` table _ Oid` of oid type. The function starts searching from the given node
|
||||
and finds the scanning node that matches the OID of the specified table.
|
||||
In the code, use the switch statement to judge the type of the node. For each scan node type that can be processed
|
||||
(for example, sequential scan, index scan, index only scan, bitmap heap scan and TID scan), the code checks whether the ID
|
||||
of the current relationship (that is, the scanned table) matches the given table OID.
|
||||
If there is a match, the function returns a pointer to the scan node.
|
||||
|
||||
For the `t _ remotequerystate` node, the code will return the scanning status of the node.
|
||||
For the `t _ extensibleplanstate' node, the code will check whether the ID of the current relationship matches
|
||||
the given table OID, and return the scanning status at the time of matching.
|
||||
|
||||
For the `t _ appendstate` node, the code will iterate through all the attached plans and recursively call the `search _ plan _ tree` function.
|
||||
If multiple matching scan nodes are found in the attached schedule, the function will return NULL.
|
||||
|
||||
-`T_AppendState' and `t _ mergeappendState': Both node types represent a method of combining multiple subquery results into one result.
|
||||
The code will traverse each subquery and recursively call the `search _ plan _ tree` function for each subquery.
|
||||
If a matching scanning node is found, and no matching node has been found before, the matching node is assigned to result.
|
||||
If multiple matching nodes are found, the function will return NULL.
|
||||
-`t _ resultstate`, `t _ limitstate`, `t _ partiteratorstate`, and `t _ materialstate` (only exists in PGXC): These node types can be
|
||||
traversed directly because they always return the current line of their input.
|
||||
-`T_SubqueryScanState: This node type represents the scanning of the subquery,
|
||||
and the code will return the scanning node in the subquery.
|
||||
-Default: If the node is not of any of the above types,
|
||||
the code will assume that it cannot traverse through the node, so it will return NULL.
|
||||
|
||||
The main purpose of this function is to find the scanning node corresponding to a specific table in the query execution plan.
|
||||
This is very useful for understanding and tracking query execution, especially
|
||||
when it is necessary to understand and debug query performance problems.
|
||||
|
||||
Generally speaking, this function is used to find the scan node corresponding to the specified table in the query execution plan.*/
|
||||
|
||||
#ifdef PGXC
|
||||
ScanState* search_plan_tree(PlanState* node, Oid table_oid)
|
||||
#else
|
||||
|
|
|
|||
Loading…
Reference in New Issue