From 223fcbe3e9acd0f306ce8cf9a8de4dbe9956d2cc Mon Sep 17 00:00:00 2001 From: chenxiaobin19 <1025221611@qq.com> Date: Thu, 18 Apr 2024 09:48:02 +0800 Subject: [PATCH] =?UTF-8?q?B=E5=BA=93=E4=B8=8B=E9=9D=9E=E4=B8=A5=E6=A0=BC?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F=E6=97=B6=E6=94=AF=E6=8C=81=E5=BE=80=E9=9D=9E?= =?UTF-8?q?=E7=A9=BA=E7=BA=A6=E6=9D=9F=E5=88=97=E6=8F=92=E5=85=A5=E7=A9=BA?= =?UTF-8?q?=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/gausskernel/runtime/executor/execMain.cpp | 5 ++-- .../runtime/executor/nodeModifyTable.cpp | 30 +++++++++++-------- .../runtime/opfusion/opfusion_update.cpp | 2 +- src/include/executor/executor.h | 11 ++++++- src/include/executor/node/nodeModifyTable.h | 3 +- src/include/knl/knl_session.h | 1 + 6 files changed, 35 insertions(+), 17 deletions(-) diff --git a/src/gausskernel/runtime/executor/execMain.cpp b/src/gausskernel/runtime/executor/execMain.cpp index 51640e44b..b4ff646b9 100755 --- a/src/gausskernel/runtime/executor/execMain.cpp +++ b/src/gausskernel/runtime/executor/execMain.cpp @@ -2576,7 +2576,8 @@ static const char *ExecRelCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *sl return NULL; } -bool ExecConstraints(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool skipAutoInc) +bool ExecConstraints(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool skipAutoInc, + bool replaceNull) { Relation rel = resultRelInfo->ri_RelationDesc; TupleDesc tupdesc = RelationGetDescr(rel); @@ -2612,7 +2613,7 @@ bool ExecConstraints(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState ExecBuildSlotValueDescription(RelationGetRelid(rel), slot, tupdesc, modifiedCols, maxfieldlen); } - bool can_ignore = estate->es_plannedstmt && estate->es_plannedstmt->hasIgnore; + bool can_ignore = (estate->es_plannedstmt && estate->es_plannedstmt->hasIgnore) || replaceNull; ereport(can_ignore ? WARNING : ERROR, (errcode(ERRCODE_NOT_NULL_VIOLATION), errmsg("null value in column \"%s\" violates not-null constraint", NameStr(tupdesc->attrs[attrChk - 1].attname)), diff --git a/src/gausskernel/runtime/executor/nodeModifyTable.cpp b/src/gausskernel/runtime/executor/nodeModifyTable.cpp index 017ff9fd2..1f221d8a6 100644 --- a/src/gausskernel/runtime/executor/nodeModifyTable.cpp +++ b/src/gausskernel/runtime/executor/nodeModifyTable.cpp @@ -1051,7 +1051,7 @@ extern PartKeyExprResult ComputePartKeyExprTuple(Relation rel, EState *estate, T */ template TupleTableSlot* ExecInsertT(ModifyTableState* state, TupleTableSlot* slot, TupleTableSlot* planSlot, EState* estate, - bool canSetTag, int options, List** partitionList, char* partExprKeyStr) + bool canSetTag, int options, List** partitionList, char* partExprKeyStr, bool replaceNull) { Tuple tuple = NULL; ResultRelInfo* result_rel_info = NULL; @@ -1160,7 +1160,7 @@ TupleTableSlot* ExecInsertT(ModifyTableState* state, TupleTableSlot* slot, Tuple if (result_rel_info->ri_FdwRoutine->GetFdwType && result_rel_info->ri_FdwRoutine->GetFdwType() == MOT_ORC) { if (result_relation_desc->rd_att->constr) { TupleTableSlot *tmp_slot = state->mt_insert_constr_slot == NULL ? slot : state->mt_insert_constr_slot; - if (!ExecConstraints(result_rel_info, tmp_slot, estate)) { + if (!ExecConstraints(result_rel_info, tmp_slot, estate, false, replaceNull)) { if (u_sess->utils_cxt.sql_ignore_strategy_val == SQL_OVERWRITE_NULL) { tuple = ReplaceTupleNullCol(RelationGetDescr(result_relation_desc), tmp_slot); /* Double check constraints in case that new val in column with not null constraints @@ -1204,7 +1204,7 @@ TupleTableSlot* ExecInsertT(ModifyTableState* state, TupleTableSlot* slot, Tuple } if (result_relation_desc->rd_att->constr) { TupleTableSlot *tmp_slot = state->mt_insert_constr_slot == NULL ? slot : state->mt_insert_constr_slot; - if (!ExecConstraints(result_rel_info, tmp_slot, estate, true)) { + if (!ExecConstraints(result_rel_info, tmp_slot, estate, true, replaceNull)) { if (u_sess->utils_cxt.sql_ignore_strategy_val == SQL_OVERWRITE_NULL) { tuple = ReplaceTupleNullCol(RelationGetDescr(result_relation_desc), tmp_slot); /* Double check constraints in case that new val in column with not null constraints @@ -2192,7 +2192,7 @@ TupleTableSlot* ExecUpdate(ItemPointer tupleid, if (result_rel_info->ri_FdwRoutine->GetFdwType && result_rel_info->ri_FdwRoutine->GetFdwType() == MOT_ORC) { if (result_relation_desc->rd_att->constr) { TupleTableSlot *tmp_slot = node->mt_insert_constr_slot == NULL ? slot : node->mt_insert_constr_slot; - if (!ExecConstraints(result_rel_info, tmp_slot, estate)) { + if (!ExecConstraints(result_rel_info, tmp_slot, estate, false, CheckPluginReplaceNull())) { if (u_sess->utils_cxt.sql_ignore_strategy_val == SQL_OVERWRITE_NULL) { tuple = ReplaceTupleNullCol(RelationGetDescr(result_relation_desc), tmp_slot); /* Double check constraints in case that new val in column with not null constraints @@ -2252,7 +2252,7 @@ lreplace: if (result_relation_desc->rd_att->constr) { TupleTableSlot *tmp_slot = node->mt_update_constr_slot == NULL ? slot : node->mt_update_constr_slot; - if (!ExecConstraints(result_rel_info, tmp_slot, estate)) { + if (!ExecConstraints(result_rel_info, tmp_slot, estate, false, CheckPluginReplaceNull())) { if (u_sess->utils_cxt.sql_ignore_strategy_val == SQL_OVERWRITE_NULL) { tuple = ReplaceTupleNullCol(RelationGetDescr(result_relation_desc), tmp_slot); /* Double check constraints in case that new val in column with not null constraints @@ -3270,13 +3270,15 @@ uint64 GetDeleteLimitCount(ExprContext* econtext, PlanState* scan, Limit *limitP return (uint64)iCount; } -static TupleTableSlot* ExecReplace(EState* estate, ModifyTableState* node, TupleTableSlot* slot, TupleTableSlot* plan_slot, int2 bucketid, int hi_options, List* partition_list, char* partExprKeyStr) +static TupleTableSlot* ExecReplace(EState* estate, ModifyTableState* node, TupleTableSlot* slot, + TupleTableSlot* plan_slot, int2 bucketid, int hi_options, List* partition_list, char* partExprKeyStr, + bool replaceNull) { Form_pg_attribute att_tup; Oid seqOid = InvalidOid; Relation rel = estate->es_result_relation_info->ri_RelationDesc; TupleTableSlot* (*ExecInsert)( - ModifyTableState* state, TupleTableSlot*, TupleTableSlot*, EState*, bool, int, List**, char*) = NULL; + ModifyTableState* state, TupleTableSlot*, TupleTableSlot*, EState*, bool, int, List**, char*, bool) = NULL; ExecInsert = ExecInsertT; @@ -3379,7 +3381,7 @@ static TupleTableSlot* ExecReplace(EState* estate, ModifyTableState* node, Tuple node, node->canSetTag); InstrCountFiltered2(&node->ps, 1); } else { - slot = ExecInsert(node, slot, plan_slot, estate, node->canSetTag, hi_options, &partition_list, partExprKeyStr); + slot = ExecInsert(node, slot, plan_slot, estate, node->canSetTag, hi_options, &partition_list, partExprKeyStr, replaceNull); } } return slot; @@ -3417,7 +3419,7 @@ static TupleTableSlot* ExecModifyTable(PlanState* state) Oid old_partition_oid = InvalidOid; bool part_key_updated = ((ModifyTable*)node->ps.plan)->partKeyUpdated; TupleTableSlot* (*ExecInsert)( - ModifyTableState* state, TupleTableSlot*, TupleTableSlot*, EState*, bool, int, List**, char*) = NULL; + ModifyTableState* state, TupleTableSlot*, TupleTableSlot*, EState*, bool, int, List**, char*, bool) = NULL; bool use_heap_multi_insert = false; int hi_options = 0; /* indicates whether it is the first time to insert, delete, update or not. */ @@ -3758,13 +3760,17 @@ static TupleTableSlot* ExecModifyTable(PlanState* state) estate->es_result_delete_remoterel = delete_remote_rel_state; #endif switch (operation) { - case CMD_INSERT: + case CMD_INSERT: { + bool replaceNull = CheckPluginReplaceNull() && !IsA(subPlanState, ResultState); if (!node->isReplace) { - slot = ExecInsert(node, slot, plan_slot, estate, node->canSetTag, hi_options, &partition_list, partExprKeyStr); + slot = ExecInsert(node, slot, plan_slot, estate, node->canSetTag, hi_options, &partition_list, + partExprKeyStr, replaceNull); } else { - slot = ExecReplace(estate, node, slot, plan_slot, bucketid, hi_options, partition_list, partExprKeyStr); + slot = ExecReplace(estate, node, slot, plan_slot, bucketid, hi_options, partition_list, + partExprKeyStr, replaceNull); } break; + } case CMD_UPDATE: if (!IS_SPQ_RUNNING) { slot = ExecUpdate(tuple_id, diff --git a/src/gausskernel/runtime/opfusion/opfusion_update.cpp b/src/gausskernel/runtime/opfusion/opfusion_update.cpp index d1777f301..c17c1e530 100644 --- a/src/gausskernel/runtime/opfusion/opfusion_update.cpp +++ b/src/gausskernel/runtime/opfusion/opfusion_update.cpp @@ -396,7 +396,7 @@ lreplace: } if (rel->rd_att->constr) { - if (!ExecConstraints(result_rel_info, m_local.m_reslot, m_c_local.m_estate)) { + if (!ExecConstraints(result_rel_info, m_local.m_reslot, m_c_local.m_estate, CheckPluginReplaceNull())) { if (u_sess->utils_cxt.sql_ignore_strategy_val != SQL_OVERWRITE_NULL) { break; } diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h index 92dfc1e88..b3691a242 100755 --- a/src/include/executor/executor.h +++ b/src/include/executor/executor.h @@ -222,7 +222,8 @@ extern void InitResultRelInfo( ResultRelInfo* resultRelInfo, Relation resultRelationDesc, Index resultRelationIndex, int instrument_options); extern ResultRelInfo* ExecGetTriggerResultRel(EState* estate, Oid relid); extern bool ExecContextForcesOids(PlanState* planstate, bool* hasoids); -extern bool ExecConstraints(ResultRelInfo* resultRelInfo, TupleTableSlot* slot, EState* estate, bool skipAutoInc = false); +extern bool ExecConstraints(ResultRelInfo* resultRelInfo, TupleTableSlot* slot, EState* estate, + bool skipAutoInc = false, bool replaceNull = false); extern void ExecWithCheckOptions(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate); extern ExecRowMark* ExecFindRowMark(EState* estate, Index rti); extern ExecAuxRowMark* ExecBuildAuxRowMark(ExecRowMark* erm, List* targetlist); @@ -721,6 +722,14 @@ extern Tuple ReplaceTupleNullCol(TupleDesc tupleDesc, TupleTableSlot* slot); extern Datum ExecEvalArrayRef(ArrayRefExprState* astate, ExprContext* econtext, bool* isNull, ExprDoneCond* isDone); extern int ResourceOwnerForgetIfExistPthreadMutex(ResourceOwner owner, pthread_mutex_t* pMutex, bool trace); +typedef bool (*replaceNullOrNotFunc)(); + +extern inline bool CheckPluginReplaceNull() +{ + return u_sess->hook_cxt.replaceNullOrNotHook != NULL ? + ((replaceNullOrNotFunc)(u_sess->hook_cxt.replaceNullOrNotHook))() : false; +} + // AutoMutexLock // Auto object for non-recursive pthread_mutex_t lock // diff --git a/src/include/executor/node/nodeModifyTable.h b/src/include/executor/node/nodeModifyTable.h index 3fe98835a..27b99ec4f 100644 --- a/src/include/executor/node/nodeModifyTable.h +++ b/src/include/executor/node/nodeModifyTable.h @@ -50,7 +50,8 @@ extern TupleTableSlot* ExecUpdate(ItemPointer tupleid, Oid oldPartitionOid, int2 template extern TupleTableSlot* ExecInsertT(ModifyTableState* state, TupleTableSlot* slot, TupleTableSlot* planSlot, - EState* estate, bool canSetTag, int options, List** partitionList, char* partExprKeyStr = NULL); + EState* estate, bool canSetTag, int options, List** partitionList, char* partExprKeyStr = NULL, + bool replaceNull = false); template extern TupleTableSlot * ExecHBucketInsertT(ModifyTableState* state, TupleTableSlot *slot, diff --git a/src/include/knl/knl_session.h b/src/include/knl/knl_session.h index ab87abb3a..36b4f5d2a 100644 --- a/src/include/knl/knl_session.h +++ b/src/include/knl/knl_session.h @@ -2927,6 +2927,7 @@ typedef struct knl_u_hook_context { void *forTsdbHook; void *pluginPlannerHook; void *groupingplannerHook; + void *replaceNullOrNotHook; } knl_u_hook_context; typedef struct knl_u_libsw_context {