From a99097439cf92d210eb43700589e525de1de0af7 Mon Sep 17 00:00:00 2001 From: gaoyang Date: Wed, 14 Jun 2023 04:18:42 -0700 Subject: [PATCH 1/2] =?UTF-8?q?iud=E6=80=A7=E8=83=BD=E6=8F=90=E5=8D=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/gausskernel/optimizer/path/clausesel.cpp | 11 +- src/gausskernel/optimizer/plan/createplan.cpp | 11 +- src/gausskernel/optimizer/util/clauses.cpp | 74 +++++++++++- src/gausskernel/optimizer/util/pathnode.cpp | 10 +- .../runtime/executor/execUtils.cpp | 21 ++++ src/gausskernel/runtime/opfusion/opfusion.cpp | 20 ++-- .../runtime/opfusion/opfusion_delete.cpp | 47 +++++++- .../runtime/opfusion/opfusion_indexscan.cpp | 52 ++++++++- .../runtime/opfusion/opfusion_insert.cpp | 9 +- .../runtime/opfusion/opfusion_update.cpp | 6 +- .../runtime/opfusion/opfusion_util.cpp | 75 +++++++------ .../storage/access/common/tupdesc.cpp | 106 ++++++++++++++++++ src/gausskernel/storage/buffer/bufmgr.cpp | 6 +- src/include/access/tupdesc.h | 1 + src/include/executor/executor.h | 1 + src/include/knl/knl_session.h | 3 + src/include/opfusion/opfusion_delete.h | 1 + src/include/opfusion/opfusion_indexscan.h | 2 + .../regress/expected/unsupported_features.out | 3 +- 19 files changed, 384 insertions(+), 75 deletions(-) diff --git a/src/gausskernel/optimizer/path/clausesel.cpp b/src/gausskernel/optimizer/path/clausesel.cpp index f9f40091f3..b89d68697a 100755 --- a/src/gausskernel/optimizer/path/clausesel.cpp +++ b/src/gausskernel/optimizer/path/clausesel.cpp @@ -768,10 +768,13 @@ Selectivity clause_selectivity(PlannerInfo* root, Node* clause, int varRelid, Jo * if it is filter for baserel and cached, or not inner join, * we should cache the var's selectivity into relation. */ - if (use_poisson && - ((RatioType_Filter == ratiotype && varratio_cached) || (jointype == JOIN_SEMI) || (jointype == JOIN_ANTI)) && - (!check_scalarop || !is_rangequery_contain_scalarop(clause, rinfo))) - get_vardata_for_filter_or_semijoin(root, clause, varRelid, s1, sjinfo, ratiotype); + if (u_sess->opfusion_reuse_ctx.opfusionObj == NULL) { + if (use_poisson && + ((RatioType_Filter == ratiotype && varratio_cached) || (jointype == JOIN_SEMI) || (jointype == JOIN_ANTI)) && + (!check_scalarop || !is_rangequery_contain_scalarop(clause, rinfo))) { + get_vardata_for_filter_or_semijoin(root, clause, varRelid, s1, sjinfo, ratiotype); + } + } #ifdef SELECTIVITY_DEBUG ereport(DEBUG4, (errmodule(MOD_OPT_JOIN), (errmsg("clause_selectivity: s1 %f", s1)))); diff --git a/src/gausskernel/optimizer/plan/createplan.cpp b/src/gausskernel/optimizer/plan/createplan.cpp index 2ad67890ea..008f4a96ae 100755 --- a/src/gausskernel/optimizer/plan/createplan.cpp +++ b/src/gausskernel/optimizer/plan/createplan.cpp @@ -2054,12 +2054,13 @@ static void add_distribute_info(PlannerInfo* root, Plan* scanPlan, Index relInde Assert(bestPath->locator_type == LOCATOR_TYPE_REPLICATED); execNodes = ng_convert_to_exec_nodes(&bestPath->distribution, bestPath->locator_type, RELATION_ACCESS_READ); } else { +#ifdef ENABLE_MULTIPLE_NODES List* quals = scanClauses; /* A hashed table may have filter quals, it's exec nodes are not equal to it's data nodes */ execNodes = GetRelationNodesByQuals( (void*)root->parse, rte->relid, relIndex, (Node*)quals, RELATION_ACCESS_READ, NULL, false); - +#endif if (execNodes == NULL) { elog(DEBUG1, "[add_distribute_info] execNodes is NULL. Oid [%u]", rte->relid); Assert(rte->relid < FirstNormalObjectId || IS_PGXC_DATANODE); @@ -7785,7 +7786,9 @@ Agg* make_agg(PlannerInfo* root, List* tlist, List* qual, AggStrategy aggstrateg if (qual != NIL && plan_rows >= HAVING_THRESHOLD && !need_stream) plan_rows = clamp_row_est(plan_rows * DEFAULT_MATCH_SEL); - if (plan->exec_nodes->baselocatortype == LOCATOR_TYPE_REPLICATED && is_execute_on_datanodes(plan)) { + if (plan->exec_nodes ==NULL){ + + } else if (plan->exec_nodes && plan->exec_nodes->baselocatortype == LOCATOR_TYPE_REPLICATED && is_execute_on_datanodes(plan)) { plan->multiple = 1.0; plan->plan_rows = plan_rows; } else { @@ -8959,7 +8962,9 @@ ModifyTable* make_modifytable(CmdType operation, bool canSetTag, List* resultRel * If the subplan already parallelize, * add local gather. */ - deparallelize_modifytable(subplans); + if (u_sess->opt_cxt.query_dop > 1) { + deparallelize_modifytable(subplans); + } foreach (subnode, subplans) { Plan* subplan = (Plan*)lfirst(subnode); diff --git a/src/gausskernel/optimizer/util/clauses.cpp b/src/gausskernel/optimizer/util/clauses.cpp index f67ce201f3..3c1ac2fe6a 100644 --- a/src/gausskernel/optimizer/util/clauses.cpp +++ b/src/gausskernel/optimizer/util/clauses.cpp @@ -4726,6 +4726,57 @@ static void sql_inline_error_callback(void* arg) errcontext("SQL function \"%s\" during inlining", callback_arg->proname); } +ExprContext* MakePerTupleExprContextForOpFusion(EState* estate) +{ + ExprContext* econtext = NULL; + MemoryContext oldcontext; + + /* Create the ExprContext node within the per-query memory context */ + oldcontext = MemoryContextSwitchTo(estate->es_query_cxt); + + econtext = makeNode(ExprContext); + + /* Initialize fields of ExprContext */ + econtext->ecxt_scantuple = NULL; + econtext->ecxt_innertuple = NULL; + econtext->ecxt_outertuple = NULL; + + econtext->ecxt_per_query_memory = estate->es_query_cxt; + + /* + * Create working memory for expression evaluation in this context. + */ + econtext->ecxt_per_tuple_memory = u_sess->iud_expr_reuse_ctx; + econtext->ecxt_param_exec_vals = estate->es_param_exec_vals; + econtext->ecxt_param_list_info = estate->es_param_list_info; + + econtext->ecxt_aggvalues = NULL; + econtext->ecxt_aggnulls = NULL; + + econtext->caseValue_datum = (Datum)0; + econtext->caseValue_isNull = true; + + econtext->domainValue_datum = (Datum)0; + econtext->domainValue_isNull = true; + + econtext->ecxt_estate = estate; + + econtext->ecxt_callbacks = NULL; + econtext->plpgsql_estate = NULL; + + /* + * Link the ExprContext into the EState to ensure it is shut down when the + * EState is freed. Because we use lcons(), shutdowns will occur in + * reverse order of creation, which may not be essential but can't hurt. + */ + estate->es_exprcontexts = lcons(econtext, estate->es_exprcontexts); + + MemoryContextSwitchTo(oldcontext); + estate->es_per_tuple_exprcontext = econtext; + + return econtext; +} + /* * evaluate_expr: pre-evaluate a constant expression * @@ -4743,11 +4794,20 @@ Expr* evaluate_expr(Expr* expr, Oid result_type, int32 result_typmod, Oid result bool const_is_null = false; int16 resultTypLen; bool resultTypByVal = false; - + bool isFusion = false; + if (u_sess->iud_expr_reuse_ctx == NULL) { + u_sess->iud_expr_reuse_ctx = AllocSetContextCreate(u_sess->top_transaction_mem_cxt, "IudExprReuseContext", ALLOCSET_DEFAULT_MINSIZE, + ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); + } /* * To use the executor, we need an EState. */ - estate = CreateExecutorState(); + if (u_sess->iud_expr_reuse_ctx != NULL) { + estate = CreateExecutorState(); + isFusion = true; + } else { + estate = CreateExecutorState(); + } /* We can use the estate's working context to avoid memory leaks. */ oldcontext = MemoryContextSwitchTo(estate->es_query_cxt); @@ -4769,6 +4829,10 @@ Expr* evaluate_expr(Expr* expr, Oid result_type, int32 result_typmod, Oid result * fortuitous, but it's not so unreasonable --- a constant expression does * not depend on context, by definition, n'est ce pas? */ + if (isFusion && estate->es_per_tuple_exprcontext == NULL) + { + MakePerTupleExprContextForOpFusion(estate); + } ExprContext* econtext = GetPerTupleExprContext(estate); if (econtext != NULL) { econtext->can_ignore = can_ignore; @@ -4796,7 +4860,11 @@ Expr* evaluate_expr(Expr* expr, Oid result_type, int32 result_typmod, Oid result } /* Release all the junk we just created */ - FreeExecutorState(estate); + if (isFusion) { + + } else { + FreeExecutorState(estate); + } /* * Make the constant result node. diff --git a/src/gausskernel/optimizer/util/pathnode.cpp b/src/gausskernel/optimizer/util/pathnode.cpp index afa419a29d..6317cc957b 100755 --- a/src/gausskernel/optimizer/util/pathnode.cpp +++ b/src/gausskernel/optimizer/util/pathnode.cpp @@ -440,12 +440,7 @@ RemoteQueryExecType SetExectypeForJoinPath(Path* inner_path, Path* outer_path) RemoteQueryExecType SetBasePathExectype(PlannerInfo* root, RelOptInfo* rel) { - RangeTblEntry* rte = root->simple_rte_array[rel->relid]; - if (rte->rtekind == RTE_RELATION && is_sys_table(rte->relid)) { - return EXEC_ON_COORDS; - } else { - return EXEC_ON_DATANODES; - } + return EXEC_ON_DATANODES; } /* @@ -2907,9 +2902,10 @@ ResultPath* create_result_path(PlannerInfo *root, RelOptInfo *rel, List* quals, pathnode->path.total_cost = u_sess->attr.attr_sql.cpu_tuple_cost; pathnode->path.stream_cost = 0; pathnode->path.exec_type = EXEC_ON_ALL_NODES; - +#ifdef ENABLE_MULTIPLE_NODES Distribution* distribution = ng_get_default_computing_group_distribution(); ng_set_distribution(&pathnode->path.distribution, distribution); +#endif } /* diff --git a/src/gausskernel/runtime/executor/execUtils.cpp b/src/gausskernel/runtime/executor/execUtils.cpp index 06d632b619..50de2f74c4 100644 --- a/src/gausskernel/runtime/executor/execUtils.cpp +++ b/src/gausskernel/runtime/executor/execUtils.cpp @@ -1300,7 +1300,28 @@ void ExecCloseIndices(ResultRelInfo* resultRelInfo) * such stuff will be cleaned up automatically in FreeExecutorState. */ } +void OpFusionExecCloseIndices(ResultRelInfo* resultRelInfo) +{ + int i; + int numIndices; + RelationPtr indexDescs; + + numIndices = resultRelInfo->ri_NumIndices; + indexDescs = resultRelInfo->ri_IndexRelationDescs; + for (i = 0; i < numIndices; i++) { + if (indexDescs[i] == NULL) + continue; /* shouldn't happen? */ + + /* Drop lock acquired by ExecOpenIndices */ + index_close(indexDescs[i], NoLock); + } + + /* + * XXX should free indexInfo array here too? Currently we assume that + * such stuff will be cleaned up automatically in FreeExecutorState. + */ +} /* * Copied from ExecInsertIndexTuples */ diff --git a/src/gausskernel/runtime/opfusion/opfusion.cpp b/src/gausskernel/runtime/opfusion/opfusion.cpp index 96b7189e01..957708065e 100644 --- a/src/gausskernel/runtime/opfusion/opfusion.cpp +++ b/src/gausskernel/runtime/opfusion/opfusion.cpp @@ -114,8 +114,9 @@ void OpFusion::InitGlobals(MemoryContext context, CachedPlanSource *psrc, List * cxt = AllocSetContextCreate(GLOBAL_PLANCACHE_MEMCONTEXT, "SharedOpfusionContext", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, SHARED_CONTEXT); } else { - cxt = AllocSetContextCreate(context, "OpfusionContext", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, - ALLOCSET_DEFAULT_MAXSIZE, STANDARD_CONTEXT); + u_sess->opfusion_cxt = cxt = AllocSetContextCreate(context, "OpfusionContext", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, + ALLOCSET_DEFAULT_MAXSIZE); + cxt = u_sess->opfusion_cxt; } MemoryContext old_context = MemoryContextSwitchTo(cxt); @@ -661,7 +662,7 @@ static void* TryReuseOpfusionObj(FusionType ftype, MemoryContext context, Cached * we save the obj without FusionType check in FusionFactory * so must check here */ - if (INSERT_FUSION != ftype) { + if (INSERT_FUSION != ftype && DELETE_FUSION != ftype) { return NULL; } @@ -681,12 +682,14 @@ static void* TryReuseOpfusionObj(FusionType ftype, MemoryContext context, Cached } /* check the resultdesc*/ - Relation rel = heap_open(rel_oid, AccessShareLock); - TupleDesc rel_tupDesc = CreateTupleDescCopy(RelationGetDescr(rel)); - heap_close(rel, AccessShareLock); - if (!equalTupleDescs(rel_tupDesc, checkOpfusionObj->m_global->m_tupDesc)) { - return NULL; + Relation rel = heap_open(rel_oid, RowExclusiveLock); + if (!opFusionReuseEqualTupleDescs(RelationGetDescr(rel), checkOpfusionObj->m_global->m_tupDesc)) + { + heap_close(rel, NoLock); + return NULL; } + + heap_close(rel, NoLock); /* call specific reset function here*/ if (!checkOpfusionObj->ResetReuseFusion(context, psrc, plantree_list, params)){ @@ -1471,4 +1474,5 @@ void AtEOXact_OpfusionReuse() * the are the sub nodes of the top transaction ctx */ u_sess->opfusion_reuse_ctx.opfusionObj = NULL; + u_sess->iud_expr_reuse_ctx = NULL; } diff --git a/src/gausskernel/runtime/opfusion/opfusion_delete.cpp b/src/gausskernel/runtime/opfusion/opfusion_delete.cpp index d0ddeb05bf..4b2d82dcc2 100644 --- a/src/gausskernel/runtime/opfusion/opfusion_delete.cpp +++ b/src/gausskernel/runtime/opfusion/opfusion_delete.cpp @@ -26,6 +26,7 @@ #include "access/tableam.h" #include "commands/matview.h" +#include "opfusion/opfusion_indexscan.h" DeleteFusion::DeleteFusion(MemoryContext context, CachedPlanSource* psrc, List* plantree_list, ParamListInfo params) : OpFusion(context, psrc, plantree_list) @@ -47,7 +48,7 @@ void DeleteFusion::InitLocals(ParamListInfo params) m_local.m_tmpvals = NULL; m_local.m_tmpisnull = NULL; - m_c_local.m_estate = CreateExecutorState(); + m_c_local.m_estate = CreateExecutorStateForOpfusion(m_local.m_localContext, m_local.m_tmpContext); m_c_local.m_estate->es_range_table = m_global->m_planstmt->rtable; m_local.m_reslot = MakeSingleTupleTableSlot(m_global->m_tupDesc); @@ -73,14 +74,14 @@ void DeleteFusion::InitGlobals() { m_global->m_reloid = getrelid(linitial_int((List*)linitial(m_global->m_planstmt->resultRelations)), m_global->m_planstmt->rtable); - Relation rel = heap_open(m_global->m_reloid, AccessShareLock); + Relation rel = heap_open(m_global->m_reloid, RowExclusiveLock); m_global->m_natts = RelationGetDescr(rel)->natts; m_global->m_tupDesc = CreateTupleDescCopy(RelationGetDescr(rel)); m_global->m_is_bucket_rel = RELATION_OWN_BUCKET(rel); m_global->m_table_type = RelationIsUstoreFormat(rel) ? TAM_USTORE : TAM_HEAP; m_global->m_tupDesc->td_tam_ops = GetTableAmRoutine(m_global->m_table_type); m_global->m_exec_func_ptr = (OpFusionExecfuncType)&DeleteFusion::ExecDelete; - heap_close(rel, AccessShareLock); + heap_close(rel, NoLock); } @@ -283,7 +284,7 @@ bool DeleteFusion::execute(long max_rows, char *completionTag) /* *************** * step 3: done * *************** */ - ExecCloseIndices(result_rel_info); + OpFusionExecCloseIndices(result_rel_info); m_local.m_isCompleted = true; m_local.m_scan->End(true); ExecDoneStepInFusion(m_c_local.m_estate); @@ -296,7 +297,45 @@ bool DeleteFusion::execute(long max_rows, char *completionTag) snprintf_s(completionTag, COMPLETION_TAG_BUFSIZE, COMPLETION_TAG_BUFSIZE - 1, "DELETE %ld", nprocessed); } securec_check_ss(errorno, "\0", "\0"); + FreeExecutorStateForOpfusion(m_c_local.m_estate); u_sess->statement_cxt.current_row_count = nprocessed; u_sess->statement_cxt.last_row_count = u_sess->statement_cxt.current_row_count; return success; } + +bool DeleteFusion::ResetReuseFusion(MemoryContext context, CachedPlanSource* psrc, List* plantree_list, ParamListInfo params) +{ + PlannedStmt *curr_plan = (PlannedStmt *)linitial(plantree_list); + int rtindex = linitial_int((List*)linitial(curr_plan->resultRelations)); + Oid curr_relid = getrelid(rtindex, curr_plan->rtable); + + if (curr_relid != m_global->m_reloid) { + return false; + } + m_global->m_planstmt = curr_plan; + + m_local.m_tmpvals = NULL; + m_local.m_tmpisnull = NULL; + + m_local.m_receiver = NULL; + m_local.m_isInsideRec = true; + + m_c_local.m_estate->es_range_table = m_global->m_planstmt->rtable; + m_c_local.m_estate->es_plannedstmt = m_global->m_planstmt; + + initParams(params); + + ModifyTable* node = (ModifyTable*)m_global->m_planstmt->planTree; + Plan *deletePlan = (Plan *)linitial(node->plans); + IndexScan* indexscan = (IndexScan *)JudgePlanIsPartIterator(deletePlan); + if(IsA(indexscan, IndexScan) && typeid(*(m_local.m_scan)) == typeid(IndexScanFusion)){ + ((IndexScanFusion *)m_local.m_scan)->ResetIndexScanFusion(indexscan, m_global->m_planstmt, + m_local.m_outParams ? m_local.m_outParams : m_local.m_params); + }else { + m_local.m_scan = ScanFusion::getScanFusion((Node*)indexscan, m_global->m_planstmt, + m_local.m_outParams ? m_local.m_outParams : m_local.m_params); + } + + + return true; +} diff --git a/src/gausskernel/runtime/opfusion/opfusion_indexscan.cpp b/src/gausskernel/runtime/opfusion/opfusion_indexscan.cpp index a61c0b6dfe..5120073db5 100644 --- a/src/gausskernel/runtime/opfusion/opfusion_indexscan.cpp +++ b/src/gausskernel/runtime/opfusion/opfusion_indexscan.cpp @@ -102,6 +102,7 @@ IndexScanFusion::IndexScanFusion(IndexScan* node, PlannedStmt* planstmt, ParamLi setAttrNo(); Relation dummyIndex = NULL; ExeceDoneInIndexFusionConstruct(m_node->scan.isPartTbl, &m_parentRel, &m_partRel, &dummyIndex, &m_rel); + m_can_reused = false; } @@ -171,7 +172,11 @@ void IndexScanFusion::Init(long max_rows) } m_epq_indexqual = m_node->indexqualorig; - m_reslot = MakeSingleTupleTableSlot(m_tupDesc, false, m_rel->rd_tam_ops); + if (m_can_reused && m_reslot != NULL) { + ExecSetSlotDescriptor(m_reslot, m_tupDesc); + } else { + m_reslot = MakeSingleTupleTableSlot(m_tupDesc, false, m_rel->rd_tam_ops); + } } HeapTuple IndexScanFusion::getTuple() @@ -255,7 +260,6 @@ void IndexScanFusion::End(bool isCompleted) return; if (m_reslot != NULL) { - (void)ExecClearTuple(m_reslot); m_reslot = NULL; } if (m_scandesc != NULL) { @@ -289,3 +293,47 @@ void IndexScanFusion::End(bool isCompleted) } } +void IndexScanFusion::ResetIndexScanFusion(IndexScan* node, PlannedStmt* planstmt, ParamListInfo params) +{ + m_node = node; + m_keyInit = false; + m_keyNum = list_length(node->indexqual); + + m_scanKeys = (ScanKey)palloc0(m_keyNum * sizeof(ScanKeyData)); + + /* init params */ + m_paramLoc = NULL; + m_paramNum = 0; + if (params != NULL) { + m_paramLoc = (ParamLoc*)palloc0(m_keyNum * sizeof(ParamLoc)); + + ListCell* lc = NULL; + int i = 0; + foreach (lc, node->indexqual) { + if (IsA(lfirst(lc), NullTest)) { + i++; + continue; + } + + Assert(IsA(lfirst(lc), OpExpr)); + + OpExpr* opexpr = (OpExpr*)lfirst(lc); + Expr* var = (Expr*)lsecond(opexpr->args); + + if (IsA(var, RelabelType)) { + var = ((RelabelType*)var)->arg; + } + + if (IsA(var, Param)) { + Param* param = (Param*)var; + m_paramLoc[m_paramNum].paramId = param->paramid; + m_paramLoc[m_paramNum++].scanKeyIndx = i; + } + i++; + } + } + m_targetList = m_node->scan.plan.targetlist; + + setAttrNo(); + m_can_reused = true; +} \ No newline at end of file diff --git a/src/gausskernel/runtime/opfusion/opfusion_insert.cpp b/src/gausskernel/runtime/opfusion/opfusion_insert.cpp index 5ad238a078..0d2b5808f2 100644 --- a/src/gausskernel/runtime/opfusion/opfusion_insert.cpp +++ b/src/gausskernel/runtime/opfusion/opfusion_insert.cpp @@ -231,7 +231,7 @@ static void ExecReleaseResource(Tuple tuple, TupleTableSlot *slot, ResultRelInfo { tableam_tops_free_tuple(tuple); (void)ExecClearTuple(slot); - ExecCloseIndices(result_rel_info); + OpFusionExecCloseIndices(result_rel_info); ExecDoneStepInFusion(estate); if (bucket_rel != NULL) { bucketCloseRelation(bucket_rel); @@ -436,7 +436,7 @@ bool InsertFusion::execute(long max_rows, char* completionTag) ************************/ unsigned long nprocessed = (this->*(m_global->m_exec_func_ptr))(rel, result_rel_info); - heap_close(rel, RowExclusiveLock); + heap_close(rel, NoLock); /**************** * step 3: done * @@ -482,10 +482,13 @@ bool InsertFusion::ResetReuseFusion(MemoryContext context, CachedPlanSource* psr InitBaseParam(targetList); // local + m_local.m_reslot->tts_tam_ops = GetTableAmRoutine(m_global->m_table_type); m_c_local.m_estate->es_range_table = NIL; m_c_local.m_estate->es_range_table = m_global->m_planstmt->rtable; m_c_local.m_estate->es_plannedstmt = m_global->m_planstmt; initParams(params); return true; -} \ No newline at end of file + +} + diff --git a/src/gausskernel/runtime/opfusion/opfusion_update.cpp b/src/gausskernel/runtime/opfusion/opfusion_update.cpp index 70b10e37b3..657d81b2b1 100644 --- a/src/gausskernel/runtime/opfusion/opfusion_update.cpp +++ b/src/gausskernel/runtime/opfusion/opfusion_update.cpp @@ -116,7 +116,7 @@ void UpdateFusion::InitGlobals() m_global->m_reloid = getrelid(linitial_int((List*)linitial(m_global->m_planstmt->resultRelations)), m_global->m_planstmt->rtable); - Relation rel = heap_open(m_global->m_reloid, AccessShareLock); + Relation rel = heap_open(m_global->m_reloid, RowExclusiveLock); m_global->m_table_type = RelationIsUstoreFormat(rel) ? TAM_USTORE : TAM_HEAP; m_global->m_exec_func_ptr = (OpFusionExecfuncType)&UpdateFusion::ExecUpdate; m_global->m_is_bucket_rel = RELATION_OWN_BUCKET(rel); @@ -124,7 +124,7 @@ void UpdateFusion::InitGlobals() m_global->m_tupDesc = CreateTupleDescCopy(RelationGetDescr(rel)); m_global->m_tupDesc->td_tam_ops = GetTableAmRoutine(m_global->m_table_type); hash_col_num = rel->rd_isblockchain ? 1 : 0; - heap_close(rel, AccessShareLock); + heap_close(rel, NoLock); #ifdef USE_ASSERT_CHECKING if (m_global->m_is_bucket_rel) { @@ -571,7 +571,7 @@ lreplace: /**************** * step 3: done * ****************/ - ExecCloseIndices(result_rel_info); + OpFusionExecCloseIndices(result_rel_info); m_local.m_isCompleted = true; m_local.m_scan->End(true); ExecDoneStepInFusion(m_c_local.m_estate); diff --git a/src/gausskernel/runtime/opfusion/opfusion_util.cpp b/src/gausskernel/runtime/opfusion/opfusion_util.cpp index 321b80a8a8..5d0a385454 100644 --- a/src/gausskernel/runtime/opfusion/opfusion_util.cpp +++ b/src/gausskernel/runtime/opfusion/opfusion_util.cpp @@ -29,6 +29,7 @@ #include "access/transam.h" #include "catalog/pg_aggregate.h" #include "catalog/pg_partition_fn.h" +#include "catalog/pg_proc.h" #include "commands/copy.h" #include "executor/node/nodeIndexscan.h" #include "libpq/pqformat.h" @@ -328,7 +329,7 @@ bool checkFusionParam(Param *param, ParamListInfo boundParams) return false; } -static bool checkFlinfo(Node *node) +static bool checkFlinfo(Node *node, bool *is_nextval) { /* check whether the flinfo satisfy conditon */ FmgrInfo *flinfo = NULL; @@ -338,6 +339,10 @@ static bool checkFlinfo(Node *node) pfree(flinfo); flinfo = NULL; return false; + } + /* Help function nextval_oid support SQL Bypass */ + if (flinfo->fn_oid == NEXTVALFUNCOID) { + *is_nextval = true; } pfree(flinfo); flinfo = NULL; @@ -360,9 +365,14 @@ static bool checkExpr(Node *node, bool is_first) if (is_first == false) { return false; } - if (!checkFlinfo(node)) { + bool is_nextval = false; + if (!checkFlinfo(node, &is_nextval)) { return false; } + if (is_nextval) + { + return true; + } bool found_ptr = true; void *ans = NULL; ans = hash_search(g_instance.exec_cxt.function_id_hashtbl, (void *)&((FuncExpr *)node)->funcid, HASH_FIND, @@ -526,10 +536,10 @@ template FusionType checkFusionIndexScan(Node *n index = index_open(indexOid, AccessShareLock); if (!OID_IS_BTREE(index->rd_rel->relam)) { - index_close(index, AccessShareLock); + index_close(index, NoLock); return NOBYPASS_ONLY_SUPPORT_BTREE_INDEX; } - index_close(index, AccessShareLock); + index_close(index, NoLock); ListCell *lc = NULL; @@ -944,7 +954,7 @@ FusionType getInsertFusionType(List *stmt_list, ParamListInfo params) return NOBYPASS_INVALID_MODIFYTABLE; } #else - if (!IsA(top_plan, ModifyTable) || top_plan->plan_node_id != 1) { + if (!IsA(top_plan, ModifyTable)) { return NOBYPASS_INVALID_MODIFYTABLE; } #endif @@ -960,7 +970,7 @@ FusionType getInsertFusionType(List *stmt_list, ParamListInfo params) /* check relation */ Index res_rel_idx = linitial_int((List*)linitial(plannedstmt->resultRelations)); Oid relid = getrelid(res_rel_idx, plannedstmt->rtable); - Relation rel = heap_open(relid, AccessShareLock); + Relation rel = heap_open(relid, RowExclusiveLock); for (int i = 0; i < rel->rd_att->natts; i++) { if (rel->rd_att->attrs[i].attisdropped) { @@ -976,27 +986,27 @@ FusionType getInsertFusionType(List *stmt_list, ParamListInfo params) Form_pg_type type_form = (Form_pg_type)GETSTRUCT(tuple); ReleaseSysCache(tuple); if (type_form->typtype != 'b') { - heap_close(rel, AccessShareLock); + heap_close(rel, NoLock); return NOBYPASS_DML_TARGET_TYPE_INVALID; } } if (checkDMLRelation(rel, plannedstmt, true, RELATION_IS_PARTITIONED(rel))) { - heap_close(rel, AccessShareLock); + heap_close(rel, NoLock); return NOBYPASS_DML_RELATION_NOT_SUPPORT; } if (RELATION_IS_PARTITIONED(rel) && !u_sess->attr.attr_sql.enable_partition_opfusion) { - heap_close(rel, AccessShareLock); + heap_close(rel, NoLock); return NOBYPASS_PARTITION_BYPASS_NOT_OPEN; } if (RELATION_IS_PARTITIONED(rel) && ENABLE_GPC) { - heap_close(rel, AccessShareLock); + heap_close(rel, NoLock); return NOBYPASS_GPC_NOT_SUPPORT_PARTITION_BYPASS; } if (checkPartitionType(rel)) { - heap_close(rel, AccessShareLock); + heap_close(rel, NoLock); return NOBYPASS_PARTITION_TYPE_NOT_SUPPORT; } - heap_close(rel, AccessShareLock); + heap_close(rel, NoLock); /* * check targetlist * maybe expr type is FuncExpr because of type conversion. @@ -1022,7 +1032,7 @@ FusionType getUpdateFusionType(List *stmt_list, ParamListInfo params) return NOBYPASS_INVALID_MODIFYTABLE; } #else - if (!IsA(top_plan, ModifyTable) || top_plan->plan_node_id != 1) { + if (!IsA(top_plan, ModifyTable)) { return NOBYPASS_INVALID_MODIFYTABLE; } #endif @@ -1059,16 +1069,16 @@ FusionType getUpdateFusionType(List *stmt_list, ParamListInfo params) IndexScan *indexscan = (IndexScan *)updatePlan; Index res_rel_idx = linitial_int((List*)linitial(plannedstmt->resultRelations)); Oid relid = getrelid(res_rel_idx, plannedstmt->rtable); - Relation rel = heap_open(relid, AccessShareLock); + Relation rel = heap_open(relid, RowExclusiveLock); if (checkDMLRelation(rel, plannedstmt, false, indexscan->scan.isPartTbl)) { - heap_close(rel, AccessShareLock); + heap_close(rel, NoLock); return NOBYPASS_DML_RELATION_NOT_SUPPORT; } if (checkPartitionType(rel)) { - heap_close(rel, AccessShareLock); + heap_close(rel, NoLock); return NOBYPASS_PARTITION_TYPE_NOT_SUPPORT; } - heap_close(rel, AccessShareLock); + heap_close(rel, NoLock); /* check target list */ if (node->partKeyUpdated) { @@ -1103,7 +1113,7 @@ FusionType getDeleteFusionType(List *stmt_list, ParamListInfo params) return NOBYPASS_INVALID_MODIFYTABLE; } #else - if (!IsA(top_plan, ModifyTable) || top_plan->plan_node_id != 1) { + if (!IsA(top_plan, ModifyTable)) { return NOBYPASS_INVALID_MODIFYTABLE; } #endif @@ -1134,20 +1144,21 @@ FusionType getDeleteFusionType(List *stmt_list, ParamListInfo params) return ttype; } - IndexScan* indexscan = (IndexScan *)deletePlan; - /* check relation */ - Index res_rel_idx = linitial_int((List*)linitial(plannedstmt->resultRelations)); - Oid relid = getrelid(res_rel_idx, plannedstmt->rtable); - Relation rel = heap_open(relid, AccessShareLock); - if (checkDMLRelation(rel, plannedstmt, false, indexscan->scan.isPartTbl)) { - heap_close(rel, AccessShareLock); - return NOBYPASS_DML_RELATION_NOT_SUPPORT; - } - if (checkPartitionType(rel)) { - heap_close(rel, AccessShareLock); - return NOBYPASS_PARTITION_TYPE_NOT_SUPPORT; - } - heap_close(rel, AccessShareLock); + + IndexScan* indexscan = (IndexScan *)deletePlan; + /* check relation */ + Index res_rel_idx = linitial_int((List*)linitial(plannedstmt->resultRelations)); + Oid relid = getrelid(res_rel_idx, plannedstmt->rtable); + Relation rel = heap_open(relid, RowExclusiveLock); + if (checkDMLRelation(rel, plannedstmt, false, indexscan->scan.isPartTbl)) { + heap_close(rel, NoLock); + return NOBYPASS_DML_RELATION_NOT_SUPPORT; + } + if (checkPartitionType(rel)) { + heap_close(rel, NoLock); + return NOBYPASS_PARTITION_TYPE_NOT_SUPPORT; + } + heap_close(rel, NoLock); /* check the number of partitions */ if (indexscan->scan.isPartTbl) { diff --git a/src/gausskernel/storage/access/common/tupdesc.cpp b/src/gausskernel/storage/access/common/tupdesc.cpp index d0cc0741fd..668a564239 100644 --- a/src/gausskernel/storage/access/common/tupdesc.cpp +++ b/src/gausskernel/storage/access/common/tupdesc.cpp @@ -664,6 +664,112 @@ bool equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2) return compareInitdefvals(tupdesc1, tupdesc2); } +bool opFusionReuseEqualTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2) +{ + int i; + + if (tupdesc1->natts != tupdesc2->natts) { + return false; + } + if (tupdesc1->tdtypeid != tupdesc2->tdtypeid) { + return false; + } + if (tupdesc1->tdhasoid != tupdesc2->tdhasoid) { + return false; + } + + if (tupdesc1->tdisredistable != tupdesc2->tdisredistable) { + return false; + } + + if (tupdesc1->td_tam_ops != tupdesc2->td_tam_ops) { + return false; + } + + for (i = 0; i < tupdesc1->natts; i++) { + Form_pg_attribute attr1 = &tupdesc1->attrs[i]; + Form_pg_attribute attr2 = &tupdesc2->attrs[i]; + + /* + * We do not need to check every single field here: we can disregard + * attrelid and attnum (which were used to place the row in the attrs + * array in the first place). It might look like we could dispense + * with checking attlen/attbyval/attalign, since these are derived + * from atttypid; but in the case of dropped columns we must check + * them (since atttypid will be zero for all dropped columns) and in + * general it seems safer to check them always. + * + * attcacheoff must NOT be checked since it's possibly not set in both + * copies. + */ + if (strcmp(NameStr(attr1->attname), NameStr(attr2->attname)) != 0) { + return false; + } + + if (attr1->attnum != attr2->attnum) { + return false; + } + + const bool cl_skip = IsClientLogicType(attr1->atttypid) && (Oid)attr1->atttypmod == attr2->atttypid; + if (attr1->atttypid != attr2->atttypid && !cl_skip) { + return false; + } + if (attr1->attstattarget != attr2->attstattarget) { + return false; + } + if (attr1->attlen != attr2->attlen) { + return false; + } + if (attr1->attndims != attr2->attndims) { + return false; + } + if (attr1->atttypmod != attr2->atttypmod && !cl_skip) { + return false; + } + if (attr1->attbyval != attr2->attbyval) { + return false; + } + if (attr1->attstorage != attr2->attstorage && !cl_skip) { + return false; + } + if (attr1->attkvtype != attr2->attkvtype) { + return false; + } + if (attr1->attcmprmode != attr2->attcmprmode) { + return false; + } + if (attr1->attalign != attr2->attalign) { + return false; + } + if (attr2->attnotnull) { + return false; + } + if (attr2->atthasdef) { + return false; + } + if (attr1->attisdropped != attr2->attisdropped) { + return false; + } + if (attr1->attislocal != attr2->attislocal) { + return false; + } + if (attr1->attinhcount != attr2->attinhcount) { + return false; + } + if (attr1->attcollation != attr2->attcollation && !cl_skip) { + return false; + } + /* attacl, attoptions and attfdwoptions are not even present... */ + } + + if (tupdesc2->constr != NULL) { + return false; + } + + /* compare the attinitdefval */ + return compareInitdefvals(tupdesc1, tupdesc2); +} + static bool ComparePgAttribute(Form_pg_attribute attr1, Form_pg_attribute attr2) { /* diff --git a/src/gausskernel/storage/buffer/bufmgr.cpp b/src/gausskernel/storage/buffer/bufmgr.cpp index 8e79236af7..285172e5fc 100644 --- a/src/gausskernel/storage/buffer/bufmgr.cpp +++ b/src/gausskernel/storage/buffer/bufmgr.cpp @@ -2032,11 +2032,7 @@ static bool ReadBuffer_common_ReadBlock(SMgrRelation smgr, char relpersistence, pgstat_count_buffer_read_time(INSTR_TIME_GET_MICROSEC(io_time)); INSTR_TIME_ADD(u_sess->instr_cxt.pg_buffer_usage->blk_read_time, io_time); pgstatCountBlocksReadTime4SessionLevel(INSTR_TIME_GET_MICROSEC(io_time)); - } else { - INSTR_TIME_SET_CURRENT(io_time); - INSTR_TIME_SUBTRACT(io_time, io_start); - pgstatCountBlocksReadTime4SessionLevel(INSTR_TIME_GET_MICROSEC(io_time)); - } + } /* check for garbage data */ if (rdStatus == SMGR_RD_CRC_ERROR) { diff --git a/src/include/access/tupdesc.h b/src/include/access/tupdesc.h index 42b8146dc9..7fd743daf3 100644 --- a/src/include/access/tupdesc.h +++ b/src/include/access/tupdesc.h @@ -195,6 +195,7 @@ extern void DecrTupleDescRefCount(TupleDesc tupdesc); } while (0) extern bool equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2); +extern bool opFusionReuseEqualTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2); extern bool equalDeltaTupleDescs(TupleDesc main_tupdesc, TupleDesc delta_tupdesc); extern void TupleDescInitEntry( diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h index 14ee0ad6ad..7f2b5828ad 100755 --- a/src/include/executor/executor.h +++ b/src/include/executor/executor.h @@ -644,6 +644,7 @@ extern Partition ExecOpenScanParitition( extern void ExecOpenIndices(ResultRelInfo* resultRelInfo, bool speculative); extern void ExecCloseIndices(ResultRelInfo* resultRelInfo); +extern void OpFusionExecCloseIndices(ResultRelInfo* resultRelInfo); extern List* ExecInsertIndexTuples( TupleTableSlot* slot, ItemPointer tupleid, EState* estate, Relation targetPartRel, Partition p, int2 bucketId, bool* conflict, Bitmapset *modifiedIdxAttrs, bool inplaceUpdated = false); diff --git a/src/include/knl/knl_session.h b/src/include/knl/knl_session.h index e27a936d42..ed5dfad493 100644 --- a/src/include/knl/knl_session.h +++ b/src/include/knl/knl_session.h @@ -2913,6 +2913,7 @@ typedef struct knl_session_context { knl_u_dolphin_errdata_context dolphin_errdata_ctx; knl_u_opfusion_reuse_context opfusion_reuse_ctx; + MemoryContext iud_expr_reuse_ctx; /* * Initialize context which records time for client connection establish. @@ -2925,6 +2926,8 @@ typedef struct knl_session_context { knl_u_hook_context hook_cxt; + MemoryContext opfusion_cxt; + /* The datetime cache in current transaction. */ TimestampTz cache_ts = 0; pg_tz* cache_timezone = NULL; diff --git a/src/include/opfusion/opfusion_delete.h b/src/include/opfusion/opfusion_delete.h index 9e0c8fb439..f437bd2d01 100644 --- a/src/include/opfusion/opfusion_delete.h +++ b/src/include/opfusion/opfusion_delete.h @@ -38,6 +38,7 @@ public: void InitLocals(ParamListInfo params); void InitGlobals(); + bool ResetReuseFusion(MemoryContext context, CachedPlanSource* psrc, List* plantree_list, ParamListInfo params); private: struct DeleteFusionLocaleVariable { EState* m_estate; diff --git a/src/include/opfusion/opfusion_indexscan.h b/src/include/opfusion/opfusion_indexscan.h index a9bb62e96d..4102dd19d0 100644 --- a/src/include/opfusion/opfusion_indexscan.h +++ b/src/include/opfusion/opfusion_indexscan.h @@ -46,8 +46,10 @@ public: TupleTableSlot* getTupleSlot(); + void ResetIndexScanFusion(IndexScan* node, PlannedStmt* planstmt, ParamListInfo params); private: struct IndexScan* m_node; + bool m_can_reused; }; #endif /* SRC_INCLUDE_OPFUSION_OPFUSION_INDEXSCAN_H_ */ \ No newline at end of file diff --git a/src/test/regress/expected/unsupported_features.out b/src/test/regress/expected/unsupported_features.out index 1692f8fb53..31e6b98a40 100644 --- a/src/test/regress/expected/unsupported_features.out +++ b/src/test/regress/expected/unsupported_features.out @@ -6,9 +6,10 @@ CREATE SEQUENCE CURRVAL_SEQUENCE_009 INCREMENT BY 100 START WITH 1; explain (costs off) INSERT INTO SEQ_CURRVAL_TABLE_009 VALUES('nextval',nextval('CURRVAL_SEQUENCE_009')); QUERY PLAN --------------------------------- + [Bypass] Insert on seq_currval_table_009 -> Result -(2 rows) +(3 rows) INSERT INTO SEQ_CURRVAL_TABLE_009 VALUES('nextval',nextval('CURRVAL_SEQUENCE_009')); INSERT INTO SEQ_CURRVAL_TABLE_009 VALUES('nextval',nextval('CURRVAL_SEQUENCE_009')); -- Gitee From a1cf9848ec81b5cfaca78161dbd4f938eebab0a9 Mon Sep 17 00:00:00 2001 From: gaoyang Date: Thu, 15 Jun 2023 01:41:23 -0700 Subject: [PATCH 2/2] clean code --- src/gausskernel/optimizer/plan/createplan.cpp | 4 +-- src/gausskernel/optimizer/util/clauses.cpp | 7 ++--- src/gausskernel/runtime/opfusion/opfusion.cpp | 5 ++-- .../runtime/opfusion/opfusion_delete.cpp | 5 ++-- .../runtime/opfusion/opfusion_insert.cpp | 1 - .../runtime/opfusion/opfusion_util.cpp | 30 +++++++++---------- 6 files changed, 22 insertions(+), 30 deletions(-) diff --git a/src/gausskernel/optimizer/plan/createplan.cpp b/src/gausskernel/optimizer/plan/createplan.cpp index 008f4a96ae..b598f88b69 100755 --- a/src/gausskernel/optimizer/plan/createplan.cpp +++ b/src/gausskernel/optimizer/plan/createplan.cpp @@ -7786,9 +7786,9 @@ Agg* make_agg(PlannerInfo* root, List* tlist, List* qual, AggStrategy aggstrateg if (qual != NIL && plan_rows >= HAVING_THRESHOLD && !need_stream) plan_rows = clamp_row_est(plan_rows * DEFAULT_MATCH_SEL); - if (plan->exec_nodes ==NULL){ + if (plan->exec_nodes ==NULL) { - } else if (plan->exec_nodes && plan->exec_nodes->baselocatortype == LOCATOR_TYPE_REPLICATED && is_execute_on_datanodes(plan)) { + } else if (plan->exec_nodes->baselocatortype == LOCATOR_TYPE_REPLICATED && is_execute_on_datanodes(plan)) { plan->multiple = 1.0; plan->plan_rows = plan_rows; } else { diff --git a/src/gausskernel/optimizer/util/clauses.cpp b/src/gausskernel/optimizer/util/clauses.cpp index 3c1ac2fe6a..940a9e132d 100644 --- a/src/gausskernel/optimizer/util/clauses.cpp +++ b/src/gausskernel/optimizer/util/clauses.cpp @@ -4829,8 +4829,7 @@ Expr* evaluate_expr(Expr* expr, Oid result_type, int32 result_typmod, Oid result * fortuitous, but it's not so unreasonable --- a constant expression does * not depend on context, by definition, n'est ce pas? */ - if (isFusion && estate->es_per_tuple_exprcontext == NULL) - { + if (isFusion && estate->es_per_tuple_exprcontext == NULL) { MakePerTupleExprContextForOpFusion(estate); } ExprContext* econtext = GetPerTupleExprContext(estate); @@ -4860,9 +4859,7 @@ Expr* evaluate_expr(Expr* expr, Oid result_type, int32 result_typmod, Oid result } /* Release all the junk we just created */ - if (isFusion) { - - } else { + if (!isFusion) { FreeExecutorState(estate); } diff --git a/src/gausskernel/runtime/opfusion/opfusion.cpp b/src/gausskernel/runtime/opfusion/opfusion.cpp index 957708065e..f26b8a13c7 100644 --- a/src/gausskernel/runtime/opfusion/opfusion.cpp +++ b/src/gausskernel/runtime/opfusion/opfusion.cpp @@ -114,7 +114,7 @@ void OpFusion::InitGlobals(MemoryContext context, CachedPlanSource *psrc, List * cxt = AllocSetContextCreate(GLOBAL_PLANCACHE_MEMCONTEXT, "SharedOpfusionContext", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, SHARED_CONTEXT); } else { - u_sess->opfusion_cxt = cxt = AllocSetContextCreate(context, "OpfusionContext", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, + u_sess->opfusion_cxt = AllocSetContextCreate(context, "OpfusionContext", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); cxt = u_sess->opfusion_cxt; } @@ -683,8 +683,7 @@ static void* TryReuseOpfusionObj(FusionType ftype, MemoryContext context, Cached /* check the resultdesc*/ Relation rel = heap_open(rel_oid, RowExclusiveLock); - if (!opFusionReuseEqualTupleDescs(RelationGetDescr(rel), checkOpfusionObj->m_global->m_tupDesc)) - { + if (!opFusionReuseEqualTupleDescs(RelationGetDescr(rel), checkOpfusionObj->m_global->m_tupDesc)) { heap_close(rel, NoLock); return NULL; } diff --git a/src/gausskernel/runtime/opfusion/opfusion_delete.cpp b/src/gausskernel/runtime/opfusion/opfusion_delete.cpp index 4b2d82dcc2..6055f95f35 100644 --- a/src/gausskernel/runtime/opfusion/opfusion_delete.cpp +++ b/src/gausskernel/runtime/opfusion/opfusion_delete.cpp @@ -328,14 +328,13 @@ bool DeleteFusion::ResetReuseFusion(MemoryContext context, CachedPlanSource* psr ModifyTable* node = (ModifyTable*)m_global->m_planstmt->planTree; Plan *deletePlan = (Plan *)linitial(node->plans); IndexScan* indexscan = (IndexScan *)JudgePlanIsPartIterator(deletePlan); - if(IsA(indexscan, IndexScan) && typeid(*(m_local.m_scan)) == typeid(IndexScanFusion)){ + if (IsA(indexscan, IndexScan) && typeid(*(m_local.m_scan)) == typeid(IndexScanFusion)) { ((IndexScanFusion *)m_local.m_scan)->ResetIndexScanFusion(indexscan, m_global->m_planstmt, m_local.m_outParams ? m_local.m_outParams : m_local.m_params); - }else { + } else { m_local.m_scan = ScanFusion::getScanFusion((Node*)indexscan, m_global->m_planstmt, m_local.m_outParams ? m_local.m_outParams : m_local.m_params); } - return true; } diff --git a/src/gausskernel/runtime/opfusion/opfusion_insert.cpp b/src/gausskernel/runtime/opfusion/opfusion_insert.cpp index 0d2b5808f2..519677a22d 100644 --- a/src/gausskernel/runtime/opfusion/opfusion_insert.cpp +++ b/src/gausskernel/runtime/opfusion/opfusion_insert.cpp @@ -489,6 +489,5 @@ bool InsertFusion::ResetReuseFusion(MemoryContext context, CachedPlanSource* psr initParams(params); return true; - } diff --git a/src/gausskernel/runtime/opfusion/opfusion_util.cpp b/src/gausskernel/runtime/opfusion/opfusion_util.cpp index 5d0a385454..5b1facfbb3 100644 --- a/src/gausskernel/runtime/opfusion/opfusion_util.cpp +++ b/src/gausskernel/runtime/opfusion/opfusion_util.cpp @@ -369,8 +369,7 @@ static bool checkExpr(Node *node, bool is_first) if (!checkFlinfo(node, &is_nextval)) { return false; } - if (is_nextval) - { + if (is_nextval) { return true; } bool found_ptr = true; @@ -1144,21 +1143,20 @@ FusionType getDeleteFusionType(List *stmt_list, ParamListInfo params) return ttype; } - - IndexScan* indexscan = (IndexScan *)deletePlan; - /* check relation */ - Index res_rel_idx = linitial_int((List*)linitial(plannedstmt->resultRelations)); - Oid relid = getrelid(res_rel_idx, plannedstmt->rtable); - Relation rel = heap_open(relid, RowExclusiveLock); - if (checkDMLRelation(rel, plannedstmt, false, indexscan->scan.isPartTbl)) { - heap_close(rel, NoLock); - return NOBYPASS_DML_RELATION_NOT_SUPPORT; - } - if (checkPartitionType(rel)) { - heap_close(rel, NoLock); - return NOBYPASS_PARTITION_TYPE_NOT_SUPPORT; - } + IndexScan* indexscan = (IndexScan *)deletePlan; + /* check relation */ + Index res_rel_idx = linitial_int((List*)linitial(plannedstmt->resultRelations)); + Oid relid = getrelid(res_rel_idx, plannedstmt->rtable); + Relation rel = heap_open(relid, RowExclusiveLock); + if (checkDMLRelation(rel, plannedstmt, false, indexscan->scan.isPartTbl)) { + heap_close(rel, NoLock); + return NOBYPASS_DML_RELATION_NOT_SUPPORT; + } + if (checkPartitionType(rel)) { heap_close(rel, NoLock); + return NOBYPASS_PARTITION_TYPE_NOT_SUPPORT; + } + heap_close(rel, NoLock); /* check the number of partitions */ if (indexscan->scan.isPartTbl) { -- Gitee