issue修复:ignore在向主键列插入null时资源泄漏修复

This commit is contained in:
teooooozhang
2023-01-11 14:46:41 +08:00
parent e7ff8013f6
commit 9e6b14bd1c
4 changed files with 56 additions and 31 deletions

View File

@ -246,6 +246,23 @@ Datum ComputePartKeyExprTuple(Relation rel, EState *estate, TupleTableSlot *slot
return val; return val;
} }
static void ExecReleaseResource(Tuple tuple, TupleTableSlot *slot, ResultRelInfo *result_rel_info, EState *estate,
Relation bucket_rel, Relation rel, Partition part, Relation partRel)
{
tableam_tops_free_tuple(tuple);
(void)ExecClearTuple(slot);
ExecCloseIndices(result_rel_info);
ExecDoneStepInFusion(estate);
if (bucket_rel != NULL) {
bucketCloseRelation(bucket_rel);
}
if (RELATION_IS_PARTITIONED(rel) && part != NULL) {
partitionClose(rel, part, RowExclusiveLock);
releaseDummyRelation(&partRel);
}
}
unsigned long InsertFusion::ExecInsert(Relation rel, ResultRelInfo* result_rel_info) unsigned long InsertFusion::ExecInsert(Relation rel, ResultRelInfo* result_rel_info)
{ {
/******************* /*******************
@ -270,6 +287,8 @@ unsigned long InsertFusion::ExecInsert(Relation rel, ResultRelInfo* result_rel_i
m_c_local.m_estate->esfRelations = NULL; m_c_local.m_estate->esfRelations = NULL;
partOid = heapTupleGetPartitionId(rel, tuple, false, m_c_local.m_estate->es_plannedstmt->hasIgnore); partOid = heapTupleGetPartitionId(rel, tuple, false, m_c_local.m_estate->es_plannedstmt->hasIgnore);
if (m_c_local.m_estate->es_plannedstmt->hasIgnore && partOid == InvalidOid) { if (m_c_local.m_estate->es_plannedstmt->hasIgnore && partOid == InvalidOid) {
ExecReleaseResource(tuple, m_local.m_reslot, result_rel_info, m_c_local.m_estate, bucket_rel, rel, part,
partRel);
return 0; return 0;
} }
part = partitionOpen(rel, partOid, RowExclusiveLock); part = partitionOpen(rel, partOid, RowExclusiveLock);
@ -301,6 +320,8 @@ unsigned long InsertFusion::ExecInsert(Relation rel, ResultRelInfo* result_rel_i
*/ */
if(!ExecConstraints(result_rel_info, m_local.m_reslot, m_c_local.m_estate, true)) { if(!ExecConstraints(result_rel_info, m_local.m_reslot, m_c_local.m_estate, true)) {
if (u_sess->utils_cxt.sql_ignore_strategy_val != SQL_OVERWRITE_NULL) { if (u_sess->utils_cxt.sql_ignore_strategy_val != SQL_OVERWRITE_NULL) {
ExecReleaseResource(tuple, m_local.m_reslot, result_rel_info, m_c_local.m_estate, bucket_rel, rel, part,
partRel);
return 0; return 0;
} }
tuple = ReplaceTupleNullCol(RelationGetDescr(result_rel_info->ri_RelationDesc), m_local.m_reslot); tuple = ReplaceTupleNullCol(RelationGetDescr(result_rel_info->ri_RelationDesc), m_local.m_reslot);
@ -336,20 +357,8 @@ unsigned long InsertFusion::ExecInsert(Relation rel, ResultRelInfo* result_rel_i
&conflictInfo, &conflictPartOid, &conflictBucketid)) { &conflictInfo, &conflictPartOid, &conflictBucketid)) {
ereport(WARNING, (errmsg("duplicate key value violates unique constraint in table \"%s\"", ereport(WARNING, (errmsg("duplicate key value violates unique constraint in table \"%s\"",
RelationGetRelationName(target_rel)))); RelationGetRelationName(target_rel))));
ExecReleaseResource(tuple, m_local.m_reslot, result_rel_info, m_c_local.m_estate, bucket_rel, rel, part,
/* clear before ended */ partRel);
tableam_tops_free_tuple(tuple);
(void)ExecClearTuple(m_local.m_reslot);
ExecCloseIndices(result_rel_info);
ExecDoneStepInFusion(m_c_local.m_estate);
if (bucket_rel != NULL) {
bucketCloseRelation(bucket_rel);
}
if (RELATION_IS_PARTITIONED(rel)) {
partitionClose(rel, part, RowExclusiveLock);
releaseDummyRelation(&partRel);
}
return 0; return 0;
} }
@ -386,25 +395,10 @@ unsigned long InsertFusion::ExecInsert(Relation rel, ResultRelInfo* result_rel_i
if (result_rel_info->ri_WithCheckOptions != NIL) if (result_rel_info->ri_WithCheckOptions != NIL)
ExecWithCheckOptions(result_rel_info, m_local.m_reslot, m_c_local.m_estate); ExecWithCheckOptions(result_rel_info, m_local.m_reslot, m_c_local.m_estate);
tableam_tops_free_tuple(tuple);
(void)ExecClearTuple(m_local.m_reslot);
/**************** /****************
* step 3: done * * step 3: done *
****************/ ****************/
ExecCloseIndices(result_rel_info); ExecReleaseResource(tuple, m_local.m_reslot, result_rel_info, m_c_local.m_estate, bucket_rel, rel, part, partRel);
ExecDoneStepInFusion(m_c_local.m_estate);
if (bucket_rel != NULL) {
bucketCloseRelation(bucket_rel);
}
if (RELATION_IS_PARTITIONED(rel)) {
partitionClose(rel, part, RowExclusiveLock);
releaseDummyRelation(&partRel);
}
return 1; return 1;
} }

View File

@ -356,7 +356,7 @@ lreplace:
if (rel->rd_att->constr) { 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)) {
if (u_sess->utils_cxt.sql_ignore_strategy_val != SQL_OVERWRITE_NULL) { if (u_sess->utils_cxt.sql_ignore_strategy_val != SQL_OVERWRITE_NULL) {
return 0; break;
} }
tup = ReplaceTupleNullCol(RelationGetDescr(result_rel_info->ri_RelationDesc), m_local.m_reslot); tup = ReplaceTupleNullCol(RelationGetDescr(result_rel_info->ri_RelationDesc), m_local.m_reslot);
/* Double check constraints in case that new val in column with not null constraints /* Double check constraints in case that new val in column with not null constraints

View File

@ -365,6 +365,24 @@ select * from t_ignore;
2 2
(2 rows) (2 rows)
-- test for insert table with primary key
drop table if exists t_pri_key_insert;
NOTICE: table "t_pri_key_insert" does not exist, skipping
create table t_pri_key_insert(id int primary key);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t_pri_key_insert_pkey" for table "t_pri_key_insert"
insert /*+ ignore_error */ into t_pri_key_insert values(null);
WARNING: null value in column "id" violates not-null constraint
DETAIL: Failing row contains (null).
insert /*+ ignore_error */ into t_pri_key_insert values(1);
insert /*+ ignore_error */ into t_pri_key_insert values(1);
WARNING: duplicate key value violates unique constraint in table "t_pri_key_insert"
select * from t_pri_key_insert;
id
----
1
(1 row)
drop table t_pri_key_insert;
-- test for update table with primary key -- test for update table with primary key
drop table if exists t_pri_key_update; drop table if exists t_pri_key_update;
NOTICE: table "t_pri_key_update" does not exist, skipping NOTICE: table "t_pri_key_update" does not exist, skipping
@ -372,6 +390,9 @@ create table t_pri_key_update(c1 int primary key, c2 int);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t_pri_key_update_pkey" for table "t_pri_key_update" NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t_pri_key_update_pkey" for table "t_pri_key_update"
insert into t_pri_key_update values(1, 101), (2, 201); insert into t_pri_key_update values(1, 101), (2, 201);
update /*+ ignore_error */ t_pri_key_update set c2 = 999 where c1 = 2; update /*+ ignore_error */ t_pri_key_update set c2 = 999 where c1 = 2;
update /*+ ignore_error */ t_pri_key_update set c1 = null where c1 = 2;
WARNING: null value in column "c1" violates not-null constraint
DETAIL: Failing row contains (null, 999).
select * from t_pri_key_update; select * from t_pri_key_update;
c1 | c2 c1 | c2
----+----- ----+-----

View File

@ -177,11 +177,21 @@ insert into t_ignore values(2);
update /*+ ignore_error */ t_ignore set num = 1 where num = 2; update /*+ ignore_error */ t_ignore set num = 1 where num = 2;
select * from t_ignore; select * from t_ignore;
-- test for insert table with primary key
drop table if exists t_pri_key_insert;
create table t_pri_key_insert(id int primary key);
insert /*+ ignore_error */ into t_pri_key_insert values(null);
insert /*+ ignore_error */ into t_pri_key_insert values(1);
insert /*+ ignore_error */ into t_pri_key_insert values(1);
select * from t_pri_key_insert;
drop table t_pri_key_insert;
-- test for update table with primary key -- test for update table with primary key
drop table if exists t_pri_key_update; drop table if exists t_pri_key_update;
create table t_pri_key_update(c1 int primary key, c2 int); create table t_pri_key_update(c1 int primary key, c2 int);
insert into t_pri_key_update values(1, 101), (2, 201); insert into t_pri_key_update values(1, 101), (2, 201);
update /*+ ignore_error */ t_pri_key_update set c2 = 999 where c1 = 2; update /*+ ignore_error */ t_pri_key_update set c2 = 999 where c1 = 2;
update /*+ ignore_error */ t_pri_key_update set c1 = null where c1 = 2;
select * from t_pri_key_update; select * from t_pri_key_update;
drop table t_pri_key_update; drop table t_pri_key_update;