B库下非严格模式时支持往非空约束列插入空值

This commit is contained in:
chenxiaobin19
2024-04-18 09:48:02 +08:00
committed by yaoxin
parent d50c38d2d2
commit 223fcbe3e9
6 changed files with 35 additions and 17 deletions

View File

@ -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)),

View File

@ -1051,7 +1051,7 @@ extern PartKeyExprResult ComputePartKeyExprTuple(Relation rel, EState *estate, T
*/
template <bool useHeapMultiInsert>
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<false>;
@ -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,

View File

@ -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;
}

View File

@ -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
//

View File

@ -50,7 +50,8 @@ extern TupleTableSlot* ExecUpdate(ItemPointer tupleid, Oid oldPartitionOid, int2
template <bool useHeapMultiInsert>
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 <bool useHeapMultiInsert>
extern TupleTableSlot *
ExecHBucketInsertT(ModifyTableState* state, TupleTableSlot *slot,

View File

@ -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 {