From 60ea55773215911f4f40f4b3f97ad3de2011804f Mon Sep 17 00:00:00 2001 From: Lohax Date: Fri, 15 Sep 2023 13:46:07 +0800 Subject: [PATCH 01/18] Update instrument.cpp --- src/gausskernel/runtime/executor/instrument.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gausskernel/runtime/executor/instrument.cpp b/src/gausskernel/runtime/executor/instrument.cpp index 59331452a..567b2a7f2 100644 --- a/src/gausskernel/runtime/executor/instrument.cpp +++ b/src/gausskernel/runtime/executor/instrument.cpp @@ -591,7 +591,8 @@ void InstrEndLoop(Instrumentation* instr) /* Skip if nothing has happened, or already shut down */ if (!instr->running) return; - + + /*If the "starttime" field of the node is not 0, the node has not called the InstrStopNode function to stop the timing, and an error may have occurred*/ if (!INSTR_TIME_IS_ZERO(instr->starttime)) { elog(DEBUG2, "InstrEndLoop called on running node"); } -- 2.34.1 From 9a54ef4161ed867ec37defbdb0b6aed7a6019f74 Mon Sep 17 00:00:00 2001 From: Lohax Date: Tue, 19 Sep 2023 19:45:45 +0800 Subject: [PATCH 02/18] Update auto_explain.cpp --- .../optimizer/commands/auto_explain.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/gausskernel/optimizer/commands/auto_explain.cpp b/src/gausskernel/optimizer/commands/auto_explain.cpp index 1cb672aa0..9e9f296c9 100644 --- a/src/gausskernel/optimizer/commands/auto_explain.cpp +++ b/src/gausskernel/optimizer/commands/auto_explain.cpp @@ -231,8 +231,20 @@ void print_parameters(const QueryDesc *queryDesc, ExplainState es) } } } + +/* exec_explain_plan + * parameter: queryDesc + * QueryDesc contains query information, such as operation type, + * query plan tree, and execution status. + * + * This function outputs the EXPLAIN information for the query + * plan and, if the EXPLAIN ANALYZE option is enabled, collects + * and displays execution statistics. + * + */ void exec_explain_plan(QueryDesc *queryDesc) { + /* Store interpretation information*/ ExplainState es; if (is_valid_query(queryDesc) && auto_explain_plan()) { INSTR_TIME_SET_CURRENT(plan_time); @@ -243,14 +255,19 @@ void exec_explain_plan(QueryDesc *queryDesc) es.verbose = true; es.analyze = false; es.timing = false; + /* Save the current performance mode*/ int old_explain_perf_mode = t_thrd.explain_cxt.explain_perf_mode; + /* Set the performance mode in the current thread to EXPLAIN_NORMAL + * to output the explain information in normal mode*/ t_thrd.explain_cxt.explain_perf_mode = (int)EXPLAIN_NORMAL; appendStringInfo(es.str, "\n---------------------------" "-NestLevel:%d----------------------------\n", u_sess->exec_cxt.nesting_level); ExplainQueryText(&es, queryDesc); appendStringInfo(es.str, "Name: %s\n", g_instance.attr.attr_common.PGXCNodeName); ExplainBeginOutput(&es); + /* Save the current memory information*/ MemoryContext current_ctx = CurrentMemoryContext; + /* exception handling*/ PG_TRY(); { ExplainPrintPlan(&es, queryDesc); @@ -258,6 +275,7 @@ void exec_explain_plan(QueryDesc *queryDesc) } PG_CATCH(); { + /*Switch to previously saved memory information to avoid memory leaks*/ MemoryContextSwitchTo(current_ctx); ErrorData* edata = CopyErrorData(); FlushErrorState(); -- 2.34.1 From 2476c078b78a71f977e188259a20fca9c5468202 Mon Sep 17 00:00:00 2001 From: Lohax Date: Thu, 21 Sep 2023 16:23:53 +0800 Subject: [PATCH 03/18] Update memnodes.h --- src/include/nodes/memnodes.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/include/nodes/memnodes.h b/src/include/nodes/memnodes.h index 3413b6dca..91f5284ba 100644 --- a/src/include/nodes/memnodes.h +++ b/src/include/nodes/memnodes.h @@ -41,9 +41,11 @@ typedef struct MemoryContextMethods { void (*init)(MemoryContext context); void (*reset)(MemoryContext context); void (*delete_context)(MemoryContext context); + /* Gets the MemoryContext block size*/ Size (*get_chunk_space)(MemoryContext context, void* pointer); bool (*is_empty)(MemoryContext context); void (*stats)(MemoryContext context, int level); + /* MemoryContext exception check*/ #ifdef MEMORY_CONTEXT_CHECKING void (*check)(MemoryContext context); #endif -- 2.34.1 From e510edd3c92a49ccc54b76d1ee33204d20ca5cb1 Mon Sep 17 00:00:00 2001 From: Lohax Date: Fri, 22 Sep 2023 22:08:46 +0800 Subject: [PATCH 04/18] Update execnodes.h --- src/include/nodes/execnodes.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index 0e4623294..2ad89da85 100755 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -1668,8 +1668,8 @@ typedef struct ScanState { List* partitions; /* list of Partition */ List* subpartitions; /* list of SubPartition */ LOCKMODE lockMode; - List* runTimeParamPredicates; - bool runTimePredicatesReady; + List* runTimeParamPredicates; /* list of predicates to be filtered*/ + bool runTimePredicatesReady; /* whether the filter predicate is ready to run*/ bool is_scan_end; /* @hdfs Mark whether iterator is over or not, if the scan uses informational constraint. */ SeqScanAccessor* ss_scanaccessor; /* prefetch related */ int part_id; -- 2.34.1 From ba44eceafcbb48d66e61a88ca67353ce6c062ab2 Mon Sep 17 00:00:00 2001 From: Lohax Date: Mon, 25 Sep 2023 15:55:20 +0800 Subject: [PATCH 05/18] Update nodeIndexscan.cpp --- src/gausskernel/runtime/executor/nodeIndexscan.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/gausskernel/runtime/executor/nodeIndexscan.cpp b/src/gausskernel/runtime/executor/nodeIndexscan.cpp index 2bcc1146b..cd4004b2d 100644 --- a/src/gausskernel/runtime/executor/nodeIndexscan.cpp +++ b/src/gausskernel/runtime/executor/nodeIndexscan.cpp @@ -95,6 +95,9 @@ static TupleTableSlot* IndexNext(IndexScanState* node) break; } } else { + /* Depending on how the table is stored, call scan_handler_idx_getnext + *to select a different API and return it to tuple + */ if ((tuple = scan_handler_idx_getnext(scandesc, direction)) == NULL) { break; } -- 2.34.1 From 26e8f894e029cc5e2e88927f25e2acc792928542 Mon Sep 17 00:00:00 2001 From: Lohax Date: Mon, 25 Sep 2023 16:02:16 +0800 Subject: [PATCH 06/18] Update nodeIndexscan.cpp --- src/gausskernel/runtime/executor/nodeIndexscan.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gausskernel/runtime/executor/nodeIndexscan.cpp b/src/gausskernel/runtime/executor/nodeIndexscan.cpp index cd4004b2d..f72bfb146 100644 --- a/src/gausskernel/runtime/executor/nodeIndexscan.cpp +++ b/src/gausskernel/runtime/executor/nodeIndexscan.cpp @@ -96,8 +96,8 @@ static TupleTableSlot* IndexNext(IndexScanState* node) } } else { /* Depending on how the table is stored, call scan_handler_idx_getnext - *to select a different API and return it to tuple - */ + *to select a different API and return the result to the tuple + */ if ((tuple = scan_handler_idx_getnext(scandesc, direction)) == NULL) { break; } -- 2.34.1 From 1720d1eecbb3c22795e0be37e9cbb5a0f9b56ac3 Mon Sep 17 00:00:00 2001 From: Lohax Date: Fri, 29 Sep 2023 11:08:44 +0800 Subject: [PATCH 07/18] Update heapam.cpp --- src/gausskernel/storage/access/heap/heapam.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/gausskernel/storage/access/heap/heapam.cpp b/src/gausskernel/storage/access/heap/heapam.cpp index 8ec90f7d8..640eb102a 100755 --- a/src/gausskernel/storage/access/heap/heapam.cpp +++ b/src/gausskernel/storage/access/heap/heapam.cpp @@ -2148,6 +2148,21 @@ static BlockNumber HeapParallelscanNextpage(HeapScanDesc scan) return page; } +/* ----------------------------------------------------------- + * heap_getnext + * ----------------------------------------------------------- + * Param: + * sscan:the description of the status of a table scan + * direction:the description of the direction of the table scan + * ----------------------------------------------------------- + * Note: + * If rs_pageatatime is true, then the heapgettup_pagemode function is called + * to read one page, otherwise the heapgettup function is called to read + * one tuple at a time. + * If the next tuple scanned is empty, returne NULL. + * Finally, increase the number of returned tuples by 1 + * ------------------------------------------------------------ + */ HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction) { HeapScanDesc scan = (HeapScanDesc) sscan; @@ -2170,7 +2185,8 @@ HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction) * the proper return buffer and return the tuple. */ HEAPDEBUG_3; /* heap_getnext returning tuple */ - + + /* increase the number of returned tuples by 1 */ pgstat_count_heap_getnext(scan->rs_base.rs_rd); Assert(!HEAP_TUPLE_IS_COMPRESSED(scan->rs_ctup.t_data)); -- 2.34.1 From a2303c1fce8270b984ab56be19bc0ae8350cafb0 Mon Sep 17 00:00:00 2001 From: Lohax Date: Fri, 29 Sep 2023 11:42:40 +0800 Subject: [PATCH 08/18] Update nodeSeqscan.cpp --- .../runtime/executor/nodeSeqscan.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/gausskernel/runtime/executor/nodeSeqscan.cpp b/src/gausskernel/runtime/executor/nodeSeqscan.cpp index aa3a1b6b6..51620840b 100644 --- a/src/gausskernel/runtime/executor/nodeSeqscan.cpp +++ b/src/gausskernel/runtime/executor/nodeSeqscan.cpp @@ -189,6 +189,25 @@ static TupleTableSlot* SeqNext(SeqScanState* node); static void ExecInitNextPartitionForSeqScan(SeqScanState* node); +/* ------------------------------------------------------ + * seq_scan_getnext_template + * ------------------------------------------------------ + * Param: + * scan:the description of the status of atable scan + * slot:tores the tuple obtained from the table + * direction:Indicates the direction of the table scan + * ------------------------------------------------------ + * Note: + * First determine how to read tuples (1) hashBucket mode + * (2) heap mode (3) uheap mode (UHeap provides a different + * data storage and management mode from the traditional Heap + * It may contain some optimizations and improvements to improve + * the performance of certain types of database workloads). + * Then call each mode of the read function, read a tuple. + * Finally, call UHeapSlotStoreUHeapTuple or heap_slot_store_heap_tuple + * to store the returned tuple tuple into the slot. + * ------------------------------------------------------ + */ template FORCE_INLINE void seq_scan_getnext_template(TableScanDesc scan, TupleTableSlot* slot, ScanDirection direction) -- 2.34.1 From dd493831fe12706b3a6d776a441f981b4085a76f Mon Sep 17 00:00:00 2001 From: Lohax Date: Fri, 29 Sep 2023 12:06:19 +0800 Subject: [PATCH 09/18] Update heapam.h --- src/include/access/heapam.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h index 8419c9e2c..36b633d10 100644 --- a/src/include/access/heapam.h +++ b/src/include/access/heapam.h @@ -98,8 +98,8 @@ typedef struct TableScanDescData TupleTableSlot *slot; /* For begin scan of CopyTo */ /* variables for batch mode scan */ - int rs_ctupRows; - int rs_maxScanRows; + int rs_ctupRows; /* current line number scanned */ + int rs_maxScanRows; /* maximum number of rows that can be scanned */ } TableScanDescData; /* struct definition appears in relscan.h */ -- 2.34.1 From 5a7f25659dad2e34b3eb8aafce5fa12c7f9a766c Mon Sep 17 00:00:00 2001 From: Lohax Date: Fri, 29 Sep 2023 23:11:20 +0800 Subject: [PATCH 10/18] Update nodeSeqscan.cpp --- src/gausskernel/runtime/executor/nodeSeqscan.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/gausskernel/runtime/executor/nodeSeqscan.cpp b/src/gausskernel/runtime/executor/nodeSeqscan.cpp index 51620840b..a315e5399 100644 --- a/src/gausskernel/runtime/executor/nodeSeqscan.cpp +++ b/src/gausskernel/runtime/executor/nodeSeqscan.cpp @@ -307,6 +307,19 @@ void ExecStoreTupleBatchMode(TableScanDesc scanDesc, TupleTableSlot** slot) } } +/* -------------------------------------------------------- + * SeqNextBatchMode + * -------------------------------------------------------- + * Param: + * node:SeqScanState类型的结点,表示扫描状态 + * -------------------------------------------------------- + * Note: + * First, obtain some status and description information of + * the scanned node, then update the node information, and + * then call ExecStoreTupleBatchMode to store the read + * utuple into the slot. + * -------------------------------------------------------- + */ static ScanBatchResult *SeqNextBatchMode(SeqScanState *node) { TableScanDesc scanDesc; @@ -320,10 +333,11 @@ static ScanBatchResult *SeqNextBatchMode(SeqScanState *node) direction = estate->es_direction; slot = &(node->scanBatchState->scanBatch.scanTupleSlotInBatch[0]); - /* get tuples from the table. */ + /* update node information */ scanDesc->rs_maxScanRows = node->scanBatchState->scanTupleSlotMaxNum; node->scanBatchState->scanfinished = tableam_scan_gettuplebatchmode(scanDesc, direction); + /* store the read utuple into the slot */ if (slot[0]->tts_tupslotTableAm == TAM_USTORE) { ExecStoreTupleBatchMode(scanDesc, slot); } else { -- 2.34.1 From 9b53900b9e206f269a00db964de178a2f9ce254e Mon Sep 17 00:00:00 2001 From: Lohax Date: Sat, 30 Sep 2023 22:48:11 +0800 Subject: [PATCH 11/18] Update nodeSeqscan.cpp --- .../runtime/executor/nodeSeqscan.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/gausskernel/runtime/executor/nodeSeqscan.cpp b/src/gausskernel/runtime/executor/nodeSeqscan.cpp index a315e5399..739cf6628 100644 --- a/src/gausskernel/runtime/executor/nodeSeqscan.cpp +++ b/src/gausskernel/runtime/executor/nodeSeqscan.cpp @@ -440,6 +440,23 @@ RangeScanInRedis reset_scan_qual(Relation curr_heap_rel, ScanState* node, bool i return node->rangeScanInRedis; } +/* ------------------------------------------------------------- + * InitBeginScan + * ------------------------------------------------------------- + * Param: + * node: SeqScanState Type structure, which represents scan status information + * current_relation: current relation to handle + * ------------------------------------------------------------- + * Note: + * This code is used to initialize the Scan information (ScanDesc), + * and it depends on whether the node corresponds to Sample Scan or + * not to select a different initialization function. (Sample Scan + * is a scanning mode that can extract some samples from a query with + * a large amount of data, query these samples, and then calculate + * the query cost and optimize the query method according to the + * query cost.) + * ------------------------------------------------------------- + */ static TableScanDesc InitBeginScan(SeqScanState* node, Relation current_relation) { TableScanDesc current_scan_desc = NULL; -- 2.34.1 From b0c0c249a7e666edbfcfc6368bd63cb8744cb4b1 Mon Sep 17 00:00:00 2001 From: Lohax Date: Sun, 1 Oct 2023 22:05:24 +0800 Subject: [PATCH 12/18] Update heapam.h --- src/include/access/heapam.h | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h index 36b633d10..46361049e 100644 --- a/src/include/access/heapam.h +++ b/src/include/access/heapam.h @@ -46,10 +46,20 @@ typedef struct SeqScanAccessor { uint32 sa_prefetch_trigger; /* the prefetch-trigger distance bewteen last prefetched buffer and currently accessed buffer */ } SeqScanAccessor; +/* ----------------------------------------------------------------- + * RangeScanInRedis + * ----------------------------------------------------------------- + * Note: + * Redis is a non-relational database. Redis is a key-value + * storage system. It supports a relatively large number of + * stored value types, including string, list, set, zset + * (sorted set), and hash. + * ----------------------------------------------------------------- + */ typedef struct RangeScanInRedis{ - uint8 isRangeScanInRedis; - uint8 sliceTotal; - uint8 sliceIndex; + uint8 isRangeScanInRedis; /* if it is a range scan in Redis */ + uint8 sliceTotal; /* total number of slices */ + uint8 sliceIndex; /* current slice index */ } RangeScanInRedis; /* -- 2.34.1 From 994b9b6927307a7dd97920d83bb2e113a16a5bd4 Mon Sep 17 00:00:00 2001 From: Lohax Date: Sun, 1 Oct 2023 22:11:28 +0800 Subject: [PATCH 13/18] Update heapam.h --- src/include/access/heapam.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h index 46361049e..c373945b5 100644 --- a/src/include/access/heapam.h +++ b/src/include/access/heapam.h @@ -50,14 +50,11 @@ typedef struct SeqScanAccessor { * RangeScanInRedis * ----------------------------------------------------------------- * Note: - * Redis is a non-relational database. Redis is a key-value - * storage system. It supports a relatively large number of - * stored value types, including string, list, set, zset - * (sorted set), and hash. + * This structure is used to store some information in redistrition. * ----------------------------------------------------------------- */ typedef struct RangeScanInRedis{ - uint8 isRangeScanInRedis; /* if it is a range scan in Redis */ + uint8 isRangeScanInRedis; /* if it is a range scan in Redistribution */ uint8 sliceTotal; /* total number of slices */ uint8 sliceIndex; /* current slice index */ } RangeScanInRedis; -- 2.34.1 From 4be53ccd0e5c6e56722c37d0698f49816e5b931d Mon Sep 17 00:00:00 2001 From: Lohax Date: Sun, 1 Oct 2023 22:37:19 +0800 Subject: [PATCH 14/18] Update nodeSeqscan.cpp --- .../runtime/executor/nodeSeqscan.cpp | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/gausskernel/runtime/executor/nodeSeqscan.cpp b/src/gausskernel/runtime/executor/nodeSeqscan.cpp index 739cf6628..d151dc754 100644 --- a/src/gausskernel/runtime/executor/nodeSeqscan.cpp +++ b/src/gausskernel/runtime/executor/nodeSeqscan.cpp @@ -415,13 +415,41 @@ void SeqScan_Init(TableScanDesc scan, SeqScanAccessor* p_accessor, Relation rela SeqScan_Pref_Quantity(scan, p_accessor, relation); } +/* ----------------------------------------------------------------- + * reset_scan_qual + * ----------------------------------------------------------------- + * Param: + * curr_heap_rel: current realation stored in heap storage + * node: ScanState type structure which indicates the scanning status + * isRangeScanInRedis: if it is a range scan in the redistribution process + * ----------------------------------------------------------------- + * Note: + * This code basically returns a RangeScanInRedis structure, which + * stores three fields.You can see the specific comments in the + * struct definition. + * + * First, if node is empty, the plain value is returned. Then, + * if the cluster size is allowed and the relation is in + * redistribution process,the init function gets the new qual and + * selects a different qual based on whether or not the node is + * vectorized reading (call ExecInitVecExpr if ScanBatch, Otherwise + * call ExecInitExpr); If the qual field in node has not been + * initialized, different qual initialization functions are called + * according to whether the node is reading vectorized (ExecInitVecExpr + * is called if it is canBatch, and ExecInitExpr is called Sotherwise). + * Concatenate rangeScanInRedis to the plain value. Finally return + * node->rangeScanInRedis. + * ----------------------------------------------------------------- + */ RangeScanInRedis reset_scan_qual(Relation curr_heap_rel, ScanState* node, bool isRangeScanInRedis) { if (node == NULL) { return {isRangeScanInRedis, 0, 0}; } + /* if the cluster size is allowed and the relation is in redistribution process */ if (u_sess->attr.attr_sql.enable_cluster_resize && RelationInRedistribute(curr_heap_rel)) { List* new_qual = eval_ctid_funcs(curr_heap_rel, node->ps.plan->qual, &node->rangeScanInRedis); + /* select a different Init function depending on whether it is ScanBatch */ if (!node->scanBatchMode) { node->ps.qual = (List*)ExecInitExpr((Expr*)new_qual, (PlanState*)&node->ps); } else { @@ -429,6 +457,7 @@ RangeScanInRedis reset_scan_qual(Relation curr_heap_rel, ScanState* node, bool i } node->ps.qual_is_inited = true; } else if (!node->ps.qual_is_inited) { + /* select a different Init function depending on whether it is ScanBatch */ if (!node->scanBatchMode) { node->ps.qual = (List*)ExecInitExpr((Expr*)node->ps.plan->qual, (PlanState*)&node->ps); } else { -- 2.34.1 From 1ccba0a209d81519e04bb34e203d2de84a6f8929 Mon Sep 17 00:00:00 2001 From: Lohax Date: Mon, 2 Oct 2023 09:36:47 +0800 Subject: [PATCH 15/18] Update nodeSeqscan.cpp --- src/gausskernel/runtime/executor/nodeSeqscan.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/gausskernel/runtime/executor/nodeSeqscan.cpp b/src/gausskernel/runtime/executor/nodeSeqscan.cpp index d151dc754..2972b4b5a 100644 --- a/src/gausskernel/runtime/executor/nodeSeqscan.cpp +++ b/src/gausskernel/runtime/executor/nodeSeqscan.cpp @@ -545,6 +545,19 @@ TableScanDesc BeginScanRelation(SeqScanState* node, Relation relation, Transacti return current_scan_desc; } +/* ------------------------------------------------------------- + * GetPartitionPruningResultInInitScanRelation + * ------------------------------------------------------------- + * Param: + * plan: SeqScan type structure which indicates the node type + * estate: Execution State + * current_relation: current relation need execute + * ------------------------------------------------------------- + * Note: + * return a PruningResult pointer, which store related + * information about partition running result + * + */ static PruningResult *GetPartitionPruningResultInInitScanRelation(SeqScan *plan, EState *estate, Relation current_relation) { -- 2.34.1 From 66cacf121c3cb89d8fa72c67b586eac28da900e5 Mon Sep 17 00:00:00 2001 From: Lohax Date: Mon, 2 Oct 2023 11:21:26 +0800 Subject: [PATCH 16/18] Update nodeSeqscan.cpp --- src/gausskernel/runtime/executor/nodeSeqscan.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/gausskernel/runtime/executor/nodeSeqscan.cpp b/src/gausskernel/runtime/executor/nodeSeqscan.cpp index 2972b4b5a..1ec18bc17 100644 --- a/src/gausskernel/runtime/executor/nodeSeqscan.cpp +++ b/src/gausskernel/runtime/executor/nodeSeqscan.cpp @@ -713,6 +713,18 @@ void InitScanRelation(SeqScanState* node, EState* estate, int eflags) ExecAssignScanType(node, RelationGetDescr(current_relation)); } +/* ---------------------------------------------------------------- + * InitRelationBatchScanEnv + * ---------------------------------------------------------------- + * Param: + * state: structure of type SeqScanState,which contains state + * information when excuting + * ---------------------------------------------------------------- + * Note: + * Initializes the column number that needs to be projected, and + * sets the column number that needs to be late read. + * ---------------------------------------------------------------- + */ static void InitRelationBatchScanEnv(SeqScanState *state) { /* so use MemContext which is not freed at all until the end. */ @@ -724,6 +736,7 @@ static void InitRelationBatchScanEnv(SeqScanState *state) return; } + /* Gets the column that needs to be projected */ List *pColList = proj->pi_acessedVarNumbers; batchstate->colNum = list_length(pColList); -- 2.34.1 From d913204af5a71406a757cff4085978248a4d7d04 Mon Sep 17 00:00:00 2001 From: Lohax Date: Mon, 2 Oct 2023 12:02:21 +0800 Subject: [PATCH 17/18] Update nodeSeqscan.cpp --- .../runtime/executor/nodeSeqscan.cpp | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/gausskernel/runtime/executor/nodeSeqscan.cpp b/src/gausskernel/runtime/executor/nodeSeqscan.cpp index 1ec18bc17..3f78d23f7 100644 --- a/src/gausskernel/runtime/executor/nodeSeqscan.cpp +++ b/src/gausskernel/runtime/executor/nodeSeqscan.cpp @@ -854,6 +854,44 @@ static SeqScanState *ExecInitSeqScanBatchMode(SeqScan *node, SeqScanState* scans return scanstate; } +/* ---------------------------------------------------------------- + * InitSeqNextMtd + * ---------------------------------------------------------------- + * Param: + * node: + * scanstate: + * ---------------------------------------------------------------- + * Note: + * This code initializes the ScanNextMtd and fillNextSlotFunc + * members of the SeqScanState struct. These two members define + * how to get the next record and how to fill the next slot + * respectively. + * + * Specifically, the code first checks whether node->tablesample + * is NULL. If NULL, it means that this is not a table sample scan, + * but a regular sequential scan. In this case, it sets ScanNextMtd + * to funciton SeqNext, which means that the usual sequential scan + * method is used to get the next record. + * + * Then checks whether the current relationship has a bucket + * (by calling the RELATION_OWN_BUCKET). If the current relationship + * owns the bucket, it selects the appropriate fill slot function + * based on the storage type (specified by rd_tam_type). + * + * If the current relationship does not own the bucket, then the + * choice of fill slot function is similar to the above. + * + * If node->tablesample is not NULL, then this is a tablesample + * scan. In this case, if the current relationship owns the bucket, + * set ScanNextMtd to function HbktSeqSampleNext; Otherwise, set + * it to function SeqSampleNext. + * + * In general, the purpose of this code is to initialize the + * sequential scan state based on the type of scan (regular + * sequential scan or table sample scan) and whether the current + * relationship owns the bucket. + * ---------------------------------------------------------------- + */ static inline void InitSeqNextMtd(SeqScan* node, SeqScanState* scanstate) { if (!node->tablesample) { -- 2.34.1 From 81db7d9d771229d9900dbe19a9c14e1bf164034f Mon Sep 17 00:00:00 2001 From: Lohax Date: Tue, 3 Oct 2023 17:25:45 +0800 Subject: [PATCH 18/18] Update tcap_version.cpp --- src/gausskernel/storage/tcap/tcap_version.cpp | 376 +++++++++++++++++- 1 file changed, 371 insertions(+), 5 deletions(-) diff --git a/src/gausskernel/storage/tcap/tcap_version.cpp b/src/gausskernel/storage/tcap/tcap_version.cpp index aad39ed3f..5b2fdfab3 100644 --- a/src/gausskernel/storage/tcap/tcap_version.cpp +++ b/src/gausskernel/storage/tcap/tcap_version.cpp @@ -54,6 +54,24 @@ #include "storage/tcap.h" #include "catalog/pg_constraint.h" +/* + * TvIsContainsForeignKey() --- + * Checks whether a given relation (table) with the specified + * OID (object identifier) contains a foreign key constraint. + * + * The expected behavior of this function is to return 'true' if + * the relationship specified by 'relid' contains foreign key + * constraints, and 'false' otherwise. The implementation of this + * function would involve querying the catalog table of the database + * system to check for foreign key constraints associated with a + * given relational OID. + * + * Param [IN] relid: It accepts a parameter called 'relid' of type + * 'Oid'. 'Oid' is commonly used in database systems to represent + * object identifiers. + * Returns [OUT]: A variable of type bool. True indicates that it + * contains foreign keys. + */ static bool TvIsContainsForeignKey(Oid relid) { Relation rbRel; @@ -69,6 +87,12 @@ static bool TvIsContainsForeignKey(Oid relid) sd = systable_beginscan(rbRel, ConstraintRelidIndexId, true, SnapshotNow, 1, &key); + /* For each tuple, check that the constraint type (contype) is + * CONSTRAINT_FOREIGN and that the constraint's relationship + * identifier (conrelid) matches the relid of the input. If + * both conditions are met, the relationship contains a foreign + * key constraint, so set isContainsForeignKey to true and break + * out of the loop. */ while ((tup = systable_getnext(sd)) != NULL) { Form_pg_constraint con = (Form_pg_constraint)GETSTRUCT(tup); @@ -85,6 +109,23 @@ static bool TvIsContainsForeignKey(Oid relid) return isContainsForeignKey; } +/* + * TvIsReferencedByForeignKey() --- + * Checks whether the specified relationship (table) is referenced + * by a foreign key. + * + * Foreign key reference relationships are often used to ensure data + * integrity, they indicate that a column in one table references a + * column in another table, and those references need to follow + * specific constraint rules. + * + * Param [IN] relid: This is the argument list of the function, which + * accepts a parameter named 'relid' of type 'Oid', the object + * identifier. This parameter is used to specify the identifier + * of the relationship (table) to be checked. + * Returns [OUT]: Return 'true' if the relation is referenced by a + * foreign key, or 'false' otherwise. + */ static bool TvIsReferencedByForeignKey(Oid relid) { Relation rbRel; @@ -96,6 +137,10 @@ static bool TvIsReferencedByForeignKey(Oid relid) sd = systable_beginscan(rbRel, InvalidOid, false, SnapshotNow, 0, NULL); + /* For each tuple, check that the constraint's reference relation + * identifier (confrelid) matches the input relid. If the condition + * is met, the relation is referenced by a foreign key constraint, + * so set isReferencedByForeignKey to true and out of the loop. */ while ((tup = systable_getnext(sd)) != NULL) { Form_pg_constraint con = (Form_pg_constraint)GETSTRUCT(tup); @@ -117,6 +162,27 @@ static bool TvForeignKeyCheck(Oid relid) return (TvIsContainsForeignKey(relid) || TvIsReferencedByForeignKey(relid)); } + +/* + * TvFeatureSupport() --- + * Its function is to check whether a table supports the timecapsule + * feature. timecapsule is a feature that allows tables to backtrack data + * at different points in time. + * + * This function determines whether the table to be checked supports + * the timecapsule feature based on a set of criteria, and returns the + * corresponding result and error message (if any). + * + * Param [IN] relid: an integer parameter that represents the OID (object + * identifier) of the table to be checked. + * Param [IN] errstr: a pointer to a string pointer that returns an error message. + * Param [IN] isTimecapsuleTable: A Boolean parameter that indicates whether + * the table to check has the timecapsule feature enabled. If it is, + * more stringent checks are carried out, such as not including or + * referencing foreign keys. + * Returns [OUT]: True indicates the table to check supports timecapsule related + * features, otherwise return false. + */ static bool TvFeatureSupport(Oid relid, char **errstr, bool isTimecapsuleTable) { Relation rel = RelationIdGetRelation(relid); @@ -128,6 +194,7 @@ static bool TvFeatureSupport(Oid relid, char **errstr, bool isTimecapsuleTable) errmsg("could not open relation with OID %u", relid))); } + /* perform a series of correlation checks */ classForm = rel->rd_rel; if (classForm->relkind != RELKIND_RELATION) { *errstr = "timecapsule feature does not support non-ordinary table"; @@ -164,7 +231,18 @@ static bool TvFeatureSupport(Oid relid, char **errstr, bool isTimecapsuleTable) return *errstr == NULL; } - +/* + * TvCheckVersionScan() --- + * This function is to check if a table supports the timecapsule feature + * and report an error if it does not. + * + * Call TvFeatureSupport to determine if the table to check supports the + * timecapsule feature, and if not, use the ereport function to throw an + * error. + * + * Param [IN] rte: Describes the tables that appear in the query. + * Returns [OUT]: void + */ void TvCheckVersionScan(RangeTblEntry *rte) { char *errstr = NULL; @@ -178,6 +256,15 @@ void TvCheckVersionScan(RangeTblEntry *rte) return; } +/* + * TvIsVersionScan() --- + * Check if a scan is a "timecapsule" version scan. + * + * Param [IN] ss: A pointer to the ScanState structure, which contains + * information about the scan. + * Returns [OUT]: Return true if the scan is the "timecapsule" version scan; + * Otherwise, return false. + */ bool TvIsVersionScan(const ScanState *ss) { EState *estate = ss->ps.state; @@ -188,7 +275,14 @@ bool TvIsVersionScan(const ScanState *ss) } /* - * Whether the plan contains version table scan. + * TvIsVersionPlan() --- + * Check if a schedule statement contains the "timecapsule" version + * of the table. + * + * Param [IN] stmt: A pointer to the PlannedStmt structure that contains + * information about the planned statement. + * Returns [OUT]: Return true if the schedule statement contains the + * "timecapsule" version of the table; Otherwise, return false. */ bool TvIsVersionPlan(const PlannedStmt *stmt) { @@ -204,6 +298,30 @@ bool TvIsVersionPlan(const PlannedStmt *stmt) return false; } +/* + * TvTransformVersionExpr() --- + * The function converts the given "timecapsule" version of the + * expression (specified by tvver) to a specific type of expression + * and checks if the expression contains a sublink. + * + * The function first calls the transformExpr function to convert the + * "timecapsule" version expression. It then checks whether the converted + * expression contains sublinks. The function casts the expression to a + * specific type based on the "timecapsule" version type (specified by + * tvtype). If the version type is a timestamp, it casts the expression + * to the TIMESTAMPTZOID type; Otherwise, it casts the expression to + * INT8OID type. Finally, the function calls assign_expr_collations + * to assign the sorting of the expression and returns the converted + * expression. + * + * Param [IN] pstate: A pointer to the ParseState structure, which + * contains information about the parsing state. + * Param [IN] tvtype: This is an enumeration value that represents + * the "timecapsule" version type, which can be timestamp + * (TV_VERSION_TIMESTAMP) or CSN (TV_VERSION_CSN). + * Param [IN] tvver: Represents the "timecapsule" version expression. + * Returns [OUT]: Represents the converted "timecapsule" version expression. + */ Node *TvTransformVersionExpr(ParseState *pstate, TvVersionType tvtype, Node *tvver) { Node *verExpr = tvver; @@ -225,7 +343,23 @@ Node *TvTransformVersionExpr(ParseState *pstate, TvVersionType tvtype, Node *tvv return verExpr; } - +/* + * TvEvalVerExpr() --- + * The main purpose is to evaluate the "timecapsule" version expressions. + * + * First try to convert tvver to a constant. If successful, it will return + * the constant directly. Otherwise, it creates a new ParseState, then calls + * the TvTransformVersionExpr function to convert the "timecapsule" version + * expression, and releases the parsing state. Next, the function calls the + * evaluate_expr function to evaluate the converted expression and convert + * the result to a constant. Double check that result is indeed Const. + * + * Param [IN] tvtype: This is an enumeration value that represents the + * "timecapsule" version type, which can be timestamp (TV_VERSION_TIMESTAMP) + * or CSN (TV_VERSION_CSN). + * Param [IN] tvver: Represents the "timecapsule" version expression. + * Returns [OUT]: Represents the evaluated "timecapsule" version expression. + */ static Const *TvEvalVerExpr(TvVersionType tvtype, Node *tvver) { Const *result = (Const *)tvver; @@ -394,6 +528,21 @@ static void TvFetchSnapCsn(int64 csn, Snapshot snap) return; } +/* + * TvFetchSnap() --- + * Get a snapshot of the "timecapsule" version. + * + * Call the function based on the "timecapsule" version type to get the + * snapshot. If the version type is timestamp, it calls the TvFetchSnapTz + * function; Otherwise, it calls the TvFetchSnapCsn function. + * + * Param [IN] type: Represents the "timecapsule" version type, which can + * be timestamp (TV_VERSION_TIMESTAMP) or CSN (TV_VERSION_CSN). + * Param [IN] value: Values that represent information about the "timecapsule" + * version. + * Returns [OUT]: Returns a pointer to the Snapshot. This snapshot represents + * the obtained "timecapsule" version snapshot. + */ static Snapshot TvFetchSnap(TvVersionType type, Const *value) { Snapshot snap = (Snapshot)palloc0(sizeof(SnapshotData)); @@ -409,6 +558,20 @@ static Snapshot TvFetchSnap(TvVersionType type, Const *value) return snap; } +/* + * TvGetSnap() --- + * The main purpose is to call the TvFetchSnap function to get + * the "timecapsule" version snapshot of the specified table and + * check for errors. + * + * Param [IN] relation: A pointer to the Relation structure, which + * contains information about the table. + * Param [IN] tvtype: Represents the "timecapsule" version type, which + * can be timestamp (TV_VERSION_TIMESTAMP) or CSN (TV_VERSION_CSN). + * Param [IN] tvver: Represents the "timecapsule" version expression. + * Returns [OUT]: Returns a pointer to the Snapshot. This snapshot represents + * the obtained "timecapsule" version snapshot. + */ static Snapshot TvGetSnap(Relation relation, TvVersionType tvtype, Node *tvver) { Const *value; @@ -426,6 +589,18 @@ static Snapshot TvGetSnap(Relation relation, TvVersionType tvtype, Node *tvver) return snap; } +/* + * TvValidateRelDDL() --- + * Check that the definition of the given table (specified by relid) + * has changed. + * + * Param [IN] relid: It accepts a parameter called 'relid' of type + * 'Oid'. 'Oid' is commonly used in database systems to represent + * object identifiers. + * Param [IN] snapcsn: This is a commit sequence number that represents + * the value to be compared with the table's change sequence number. + * Returns [OUT]: void + */ static void TvValidateRelDDL(Oid relid, CommitSeqNo snapcsn) { Relation rel = RelationIdGetRelation(relid); @@ -447,8 +622,18 @@ static void TvValidateRelDDL(Oid relid, CommitSeqNo snapcsn) } /* - * Choose user-specified snapshot if TimeCapsule clause exists, otherwise - * estate->es_snapshot instead. + * TvChooseScanSnap() --- + * Select the appropriate snapshot to scan based on the given table, + * scan, and scan states (specified by relation, scan, and ss). + * + * Param [IN] relation: A pointer to the Relation structure, which contains + * information about the table. + * Param [IN] scan: A pointer to the Scan structure that contains information + * about the scan. + * Param [IN] ss: A pointer to the ScanState structure that contains information + * about the state of the scan. + * Returns [OUT]: Returns a pointer to the Snapshot. This snapshot represents + * the selected snapshot. */ Snapshot TvChooseScanSnap(Relation relation, Scan *scan, ScanState *ss) { @@ -481,6 +666,22 @@ Snapshot TvChooseScanSnap(Relation relation, Scan *scan, ScanState *ss) return snap; } +/* + * TvDeleteDelta() --- + * Deletes all tuples for a given table (specified by relid). + * + * The function first opens the relationship (that is, the table) specified by + * relid. It then scans the relationship and gets the next tuple. If a tuple + * is found, it deletes the tuple. This process repeats until there are no + * more tuples. Finally, the function ends the scan and closes the relationship. + * + * Param [IN] relid: It accepts a parameter called 'relid' of type 'Oid'. + * 'Oid' is commonly used in database systems to represent object + * identifiers. + * Param [IN] snap: A pointer to the Snapshot structure that contains + * information about the snapshot. + * Returns [OUT]: void + */ void TvDeleteDelta(Oid relid, Snapshot snap) { Relation rel; @@ -500,6 +701,19 @@ void TvDeleteDelta(Oid relid, Snapshot snap) return; } +/* + * TvUheapDeleteDeltaRel() --- + * If partRel is NULL, all tuples of the rel table are deleted, otherwise all + * tuples of the partRel table are deleted. + * + * Param [IN] rel & partRel: A pointer to the Relation structure, which contains + * information about the table. + * Param [IN] p: A pointer to a Partition structure that contains information about + * the partition. + * Param [IN] snap: A pointer to the Snapshot structure that contains + * information about the snapshot. + * Returns [OUT]: void + */ void TvUheapDeleteDeltaRel(Relation rel, Relation partRel, Partition p, Snapshot snap) { TableScanDesc sd; @@ -597,6 +811,18 @@ void TvUheapDeleteDeltaPart(Relation rel, Oid relid, Snapshot snap) return; } +/* + * TvUheapDeleteDelta() --- + * Deletes all tuples for a given table (specified by relid).This function + * is used to process tables stored in Uheap mode. + * + * Param [IN] relid: It accepts a parameter called 'relid' of type 'Oid'. + * 'Oid' is commonly used in database systems to represent object + * identifiers. + * Param [IN] snap: A pointer to the Snapshot structure that contains + * information about the snapshot. + * Returns [OUT]: void + */ void TvUheapDeleteDelta(Oid relid, Snapshot snap) { Relation rel = heap_open(relid, NoLock); @@ -609,6 +835,16 @@ void TvUheapDeleteDelta(Oid relid, Snapshot snap) heap_close(rel, NoLock); } +/* + * TvFetchTuple() --- + * Gets the next tuple pointed to by the table scan descriptor and returns + * a copy of that tuple. If there are no more tuples, it will return NULL. + * + * Param [IN] arg: A pointer to any type, which will be converted to type + * TableScanDesc and used to get the next tuple. + * Returns [OUT]: A pointer of type TvFetchTupleHook. If the next tuple is obtained, + * a copy of that tuple is returned. Otherwise, NULL is returned. + */ typedef HeapTuple (*TvFetchTupleHook)(void *arg); static HeapTuple TvFetchTuple(void *arg) { @@ -617,12 +853,43 @@ static HeapTuple TvFetchTuple(void *arg) return tup ? (HeapTuple)tableam_tops_copy_tuple(tup) : NULL; } +/* + * TvUheapFetchTuple() --- + * Gets the next tuple pointed to by the table scan descriptor and returns + * a copy of that tuple. If there are no more tuples, it will return NULL. + */ typedef UHeapTuple (*TvUheapFetchTupleHook)(void *arg); static UHeapTuple TvUheapFetchTuple(void *arg) { return (UHeapTuple)tableam_scan_getnexttuple((TableScanDesc)arg, ForwardScanDirection); } +/* + * TvBatchInsert() --- + * Batch inserts tuples into a table and updates any associated indexes. + * + * The function first switches to a short memory context to prevent memory leaks + * when calling tableam_tuple_multi_insert. It then calls tableam_tuple_multi_insert + * to insert all tuples in the buffer into the table. After that, it switches back + * to its original memory context. + * If the table has any indexes, the function traverses all inserted tuples and + * calls ExecInsertIndexTuples on each tuple to update the index. Finally, it + * frees the list returned by ExecInsertIndexTuples. + * + * Param [IN] rel: A pointer to the Relation structure, which contains information + * about the table. + * Param [IN] estate: An execution state object that contains all the information + * needed to execute the query. + * Param [IN] mycid: ID of the inserted column + * Param [IN] hiOptions: An option flag that controls the behavior of an insert operation. + * Param [IN] resultRelInfo: A result relationship information object that contains + * information about the target relation(table). + * Param [IN] myslot: Stores the tuple to be inserted. + * Param [IN] bistate: Select different policies and manage batch insert operations. + * Param [IN] nBufferedTuples: Represents the number of tuples in the buffer. + * Param [IN] bufferedTuples: A pointer to a heap tuple array, indicating the tuple to be inserted. + * Returns [OUT]:void + */ static void TvBatchInsert(Relation rel, EState *estate, CommandId mycid, int hiOptions, ResultRelInfo *resultRelInfo, TupleTableSlot *myslot, BulkInsertState bistate, @@ -666,6 +933,31 @@ static void TvBatchInsert(Relation rel, EState *estate, CommandId mycid, return; } +/* + * TvInsertLostImpl + * Batch inserts lost tuples into a table and updates any associated indexes. + * + * The function first creates an execution state object and a result relationship + * information object, and opens all indexes of the table. It then initializes a + * tuple table slot and allocates memory to store the tuple to be inserted. + * Then enters an infinite loop, in which it uses the fetchTupleHook function to + * fetch the next tuple and store it in the tuple table slot. If the tuple + * satisfies all the constraints of the table, it adds the tuple to the buffer. + * When the buffer is full or the total size of all tuples in the buffer exceeds + * the preset maximum, the function calls TvBatchInsert to insert all tuples in + * the buffer into the table and empty the buffer. + * When there are no more tuples to fetch, the function exits the loop and inserts + * any tuples remaining in the buffer into the table. Finally, the function releases + * all allocated resources and returns. + * + * Param [IN] rel: A pointer to the Relation structure, which contains information + * about the table. + * Param [IN] snap: A pointer to the Snapshot structure that contains information + * about the snapshot. + * Param [IN] fetchTupleHook: A function pointer to a function that gets a tuple. + * Param [IN] arg: It should be a pointer to a bunch of tuples. + * Returns [OUT]: void + */ const int MAX_BUFFERED_TUPLES_TCAP = 1000; const int MAX_BUFFERED_TUPLES_NUM_TCAP = 65535; static void TvInsertLostImpl(Relation rel, Snapshot snap, TvFetchTupleHook fetchTupleHook, void *arg) @@ -773,6 +1065,10 @@ static void TvInsertLostImpl(Relation rel, Snapshot snap, TvFetchTupleHook fetch return; } +/* + * TvUheapInsertLostImpl() --- + * As for TvInsertLostImpl, please read the notes for TvInsertLostImpl. + */ static void TvUheapInsertLostImpl(Relation rel, Relation partRel, Partition p, Snapshot snap, TvUheapFetchTupleHook fetchTupleHook, void *arg) { @@ -847,6 +1143,21 @@ static void TvUheapInsertLostImpl(Relation rel, Relation partRel, Partition p, return; } +/* + * TvInsertLost()--- + * Call the TvInsertLostImpl function to insert the "missing" tuple into a table. + * + * First opens the table specified by relid and starts a table scan. It then calls + * the TvInsertLostImpl function to get and insert the "missing" tuple. Finally, it + * ends the table scan and closes the table. + * + * Param [IN] relid: It accepts a parameter called 'relid' of type 'Oid'. + * 'Oid' is commonly used in database systems to represent object + * identifiers. + * Param [IN] snap: A pointer to the Snapshot structure that contains + * information about the snapshot. + * Returns [OUT]: void + */ void TvInsertLost(Oid relid, Snapshot snap) { Relation rel; @@ -865,6 +1176,23 @@ void TvInsertLost(Oid relid, Snapshot snap) return; } +/* + * TvUheapInsertLostRel() --- + * Inserts a lost tuple into a table(rel) or a part table(partRel). + * + * First check if partRel is NULL. If so, it starts scanning the tables specified + * by relid; Otherwise, it starts scanning the table parts specified by partRel. + * It then calls the TvUheapInsertLostImpl function to get and insert the "lost" + * tuple. + * + * Param [IN] rel & partRel: A pointer to the Relation structure, which contains + * information about the table. + * Param [IN] p: A pointer to a Partition structure that contains information about + * the partition. + * Param [IN] snap: A pointer to the Snapshot structure that contains information + * about the snapshot. + * Returns [OUT]: void + */ void TvUheapInsertLostRel(Relation rel, Relation partRel, Partition p, Snapshot snap) { TableScanDesc sd; @@ -879,6 +1207,29 @@ void TvUheapInsertLostRel(Relation rel, Relation partRel, Partition p, Snapshot return; } +/* + * TvUheapInsertLostPart() --- + * Insert the lost tuple into the partition of a table. + * + * The function first gets all the partitions of the table specified by relid. + * It then traverses all partitions and does the following for each partition: + * 1. Opens the partition and gets its relational objects. + * 2. Check whether the partition has subpartitions. If so, it gets all the + * subpartitions and calls the TvUheapInsertLostRel function on each subpartition + * to insert the "lost" tuple. It then closes the subpartition and frees the + * relational object. + * 3. If the partition has no subpartitions, it directly calls the TvUheapInsertLostRel + * function to insert the "lost" tuple. + * 4. Finally, it closes the partition and frees the relational object. + * + * Param [IN] rel: A pointer to the Relation structure, which contains information + * about the table. + * Param [IN] relid: It accepts a parameter called 'relid' of type 'Oid'.'Oid' + * is commonly used in database systems to represent object identifiers. + * Param [IN] snap: A pointer to the Snapshot structure that contains information + * about the snapshot. + * Returns [OUT]: void + */ void TvUheapInsertLostPart(Relation rel, Oid relid, Snapshot snap) { List* partTupleList = NIL; @@ -934,6 +1285,14 @@ void TvUheapInsertLost(Oid relid, Snapshot snap) return; } +/* + * TvCheckVersionRestore() --- + * Check whether the version of the table is allowed to be restored, + * and check whether the current user has permission to do so. + * + * Param [IN] rel: Represents the version of the table to be recovered. + * Returns [OUT]: void + */ static void TvCheckVersionRestore(Relation rel) { char *errstr = NULL; @@ -957,6 +1316,13 @@ static void TvCheckVersionRestore(Relation rel) return; } +/* + * TvRestoreVersion() --- + * Restores a version of a table. + * + * Param [IN] stmt: Contains information and version information about the table to be recovered. + * Retuens [OUT]: void + */ void TvRestoreVersion(TimeCapsuleStmt *stmt) { Relation rel; -- 2.34.1