!1908 issue处理:ignore_hint在interval分区表中插入null值时,报error而不是warning

Merge pull request !1908 from zhangzhixian/issue_handling_for_interval_partition
This commit is contained in:
opengauss-bot
2022-07-20 10:33:18 +00:00
committed by Gitee
5 changed files with 120 additions and 10 deletions

View File

@ -6260,7 +6260,7 @@ Oid AddNewIntervalPartition(Relation rel, void* insertTuple, bool isDDL)
UnlockRelationForAccessIntervalPartTabIfHeld(rel);
/* it will accept invalidation messages generated by other sessions in lockRelationForAddIntervalPartition. */
LockRelationForAddIntervalPartition(rel);
partitionRoutingForTuple(rel, insertTuple, u_sess->catalog_cxt.route);
partitionRoutingForTuple(rel, insertTuple, u_sess->catalog_cxt.route, false);
/* if the partition exists, return partition's oid */
if (u_sess->catalog_cxt.route->fileExist) {
@ -7132,7 +7132,7 @@ Oid heapTupleGetPartitionId(Relation rel, void *tuple, bool isDDL, bool canIgnor
Oid partitionid = InvalidOid;
/* get routing result */
partitionRoutingForTuple(rel, tuple, u_sess->catalog_cxt.route);
partitionRoutingForTuple(rel, tuple, u_sess->catalog_cxt.route, canIgnore);
/* if the partition exists, return partition's oid */
if (u_sess->catalog_cxt.route->fileExist) {

View File

@ -2124,11 +2124,12 @@ lreplace:
bool row_movement = false;
bool need_create_file = false;
int seqNum = -1;
bool can_ignore = estate->es_plannedstmt->hasIgnore;
if (!partKeyUpdate) {
row_movement = false;
new_partId = oldPartitionOid;
} else {
partitionRoutingForTuple(result_relation_desc, tuple, u_sess->exec_cxt.route);
partitionRoutingForTuple(result_relation_desc, tuple, u_sess->exec_cxt.route, can_ignore);
if (u_sess->exec_cxt.route->fileExist) {
new_partId = u_sess->exec_cxt.route->partitionId;
@ -2136,11 +2137,11 @@ lreplace:
Partition part = partitionOpen(result_relation_desc, new_partId, RowExclusiveLock);
Relation partRel = partitionGetRelation(result_relation_desc, part);
partitionRoutingForTuple(partRel, tuple, u_sess->exec_cxt.route);
partitionRoutingForTuple(partRel, tuple, u_sess->exec_cxt.route, can_ignore);
if (u_sess->exec_cxt.route->fileExist) {
new_partId = u_sess->exec_cxt.route->partitionId;
} else {
int level = estate->es_plannedstmt->hasIgnore ? WARNING : ERROR;
int level = can_ignore ? WARNING : ERROR;
ereport(level, (errmodule(MOD_EXECUTOR),
(errcode(ERRCODE_PARTITION_ERROR),
errmsg("fail to update partitioned table \"%s\"",
@ -2150,7 +2151,7 @@ lreplace:
releaseDummyRelation(&partRel);
partitionClose(result_relation_desc, part, NoLock);
if (!u_sess->exec_cxt.route->fileExist && estate->es_plannedstmt->hasIgnore) {
if (!u_sess->exec_cxt.route->fileExist && can_ignore) {
return NULL;
}
}
@ -2174,7 +2175,7 @@ lreplace:
* it can not be a range area
*/
if (u_sess->exec_cxt.route->partArea != PART_AREA_INTERVAL) {
if (epqstate->parentestate->es_plannedstmt->hasIgnore) {
if (can_ignore) {
ereport(WARNING, (errmsg("fail to update partitioned table \"%s\".new tuple does not "
"map to any table partition.",
RelationGetRelationName(result_relation_desc))));
@ -2235,7 +2236,7 @@ lreplace:
/*
* check constraints first if SQL has keyword IGNORE
*/
if (estate->es_plannedstmt && estate->es_plannedstmt->hasIgnore &&
if (can_ignore &&
!ExecCheckIndexConstraints(slot, estate, fake_relation, partition, &isgpi, bucketid,
&conflictInfo, &conflictPartOid, &conflictBucketid)) {
ereport(WARNING, (errmsg("duplicate key value violates unique constraint in table \"%s\"",
@ -2447,7 +2448,7 @@ lreplace:
/*
* check constraints first if SQL has keyword IGNORE
*/
if (estate->es_plannedstmt && estate->es_plannedstmt->hasIgnore &&
if (can_ignore &&
!ExecCheckIndexConstraints(slot, estate, fake_insert_relation, insert_partition, &isgpi,
bucketid, &conflictInfo, &conflictPartOid, &conflictBucketid)) {
ereport(WARNING, (errmsg("duplicate key value violates unique constraint in table \"%s\"",

View File

@ -146,7 +146,7 @@ typedef struct HashPartitionMap {
} \
} while (0)
#define partitionRoutingForTuple(rel, tuple, partIdentfier) \
#define partitionRoutingForTuple(rel, tuple, partIdentfier, canIgnore) \
do { \
TupleDesc tuple_desc = NULL; \
int2vector *partkey_column = NULL; \
@ -169,6 +169,14 @@ typedef struct HashPartitionMap {
transformDatum2Const((rel)->rd_att, partkey_column->values[i], column_raw, isnull, &consts[i]); \
} \
if (PartitionMapIsInterval((rel)->partMap) && values[0]->constisnull) { \
if (canIgnore) { \
/* treat type as PART_TYPE_RANGE because PART_TYPE_INTERVAL will create a new partition. \
* this will be handled by caller and directly return */ \
(partIdentfier)->partArea = PART_AREA_RANGE; \
(partIdentfier)->fileExist = false; \
(partIdentfier)->partitionId = InvalidOid; \
break; \
} \
ereport(ERROR, \
(errcode(ERRCODE_INTERNAL_ERROR), errmsg("inserted partition key does not map to any partition"), \
errdetail("inserted partition key cannot be NULL for interval-partitioned table"))); \

View File

@ -304,6 +304,71 @@ select * from t_ignore;
3000 | abc
(1 row)
-- test for interval partition table
drop table if exists t_interval_partition cascade;
NOTICE: table "t_interval_partition" does not exist, skipping
create table t_interval_partition
(
id1 integer primary key,
id3 integer,
c_3 date
)
PARTITION BY RANGE (c_3) INTERVAL('1 year')
(
PARTITION P1 values less than ('2018-03-16 16:27:04'),
PARTITION P2 values less than ('2020-03-16 16:27:04'),
PARTITION P4 values less than ('2022-03-16 16:27:04')
) ENABLE ROW MOVEMENT;
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t_interval_partition_pkey" for table "t_interval_partition"
-- test for interval partition table, opfusion: on
set enable_partition_opfusion = on;
insert into t_interval_partition values (1, 1, null);
ERROR: inserted partition key does not map to any partition
DETAIL: inserted partition key cannot be NULL for interval-partitioned table
insert /*+ ignore_error */ into t_interval_partition values (1, 1, null);
WARNING: inserted partition key does not map to any table partition
select * from t_interval_partition;
id1 | id3 | c_3
-----+-----+-----
(0 rows)
insert into t_interval_partition values (1, 1, '2023-02-01 00:00:00');
update t_interval_partition set c_3 = null where id1 = 1;
ERROR: inserted partition key does not map to any partition
DETAIL: inserted partition key cannot be NULL for interval-partitioned table
update /*+ ignore_error */ t_interval_partition set c_3 = null where id1 = 1;
WARNING: fail to update partitioned table "t_interval_partition".new tuple does not map to any table partition.
select * from t_interval_partition;
id1 | id3 | c_3
-----+-----+------------
1 | 1 | 02-01-2023
(1 row)
-- test for interval partition table, opfusion: off
delete from t_interval_partition;
set enable_partition_opfusion = off;
insert into t_interval_partition values (1, 1, null);
ERROR: inserted partition key does not map to any partition
DETAIL: inserted partition key cannot be NULL for interval-partitioned table
insert /*+ ignore_error */ into t_interval_partition values (1, 1, null);
WARNING: inserted partition key does not map to any table partition
select * from t_interval_partition;
id1 | id3 | c_3
-----+-----+-----
(0 rows)
insert into t_interval_partition values (1, 1, '2023-02-01 00:00:00');
update t_interval_partition set c_3 = null where id1 = 1;
ERROR: inserted partition key does not map to any partition
DETAIL: inserted partition key cannot be NULL for interval-partitioned table
update /*+ ignore_error */ t_interval_partition set c_3 = null where id1 = 1;
WARNING: fail to update partitioned table "t_interval_partition".new tuple does not map to any table partition.
select * from t_interval_partition;
id1 | id3 | c_3
-----+-----+------------
1 | 1 | 02-01-2023
(1 row)
set enable_opfusion = on;
set enable_partition_opfusion = off;
drop table t_ignore;

View File

@ -153,6 +153,42 @@ insert into t_ignore values(3000, 'abc');
update /*+ ignore_error */ t_ignore set col1 = 20000 where col1 = 3000;
select * from t_ignore;
-- test for interval partition table
drop table if exists t_interval_partition cascade;
create table t_interval_partition
(
id1 integer primary key,
id3 integer,
c_3 date
)
PARTITION BY RANGE (c_3) INTERVAL('1 year')
(
PARTITION P1 values less than ('2018-03-16 16:27:04'),
PARTITION P2 values less than ('2020-03-16 16:27:04'),
PARTITION P4 values less than ('2022-03-16 16:27:04')
) ENABLE ROW MOVEMENT;
-- test for interval partition table, opfusion: on
set enable_partition_opfusion = on;
insert into t_interval_partition values (1, 1, null);
insert /*+ ignore_error */ into t_interval_partition values (1, 1, null);
select * from t_interval_partition;
insert into t_interval_partition values (1, 1, '2023-02-01 00:00:00');
update t_interval_partition set c_3 = null where id1 = 1;
update /*+ ignore_error */ t_interval_partition set c_3 = null where id1 = 1;
select * from t_interval_partition;
-- test for interval partition table, opfusion: off
delete from t_interval_partition;
set enable_partition_opfusion = off;
insert into t_interval_partition values (1, 1, null);
insert /*+ ignore_error */ into t_interval_partition values (1, 1, null);
select * from t_interval_partition;
insert into t_interval_partition values (1, 1, '2023-02-01 00:00:00');
update t_interval_partition set c_3 = null where id1 = 1;
update /*+ ignore_error */ t_interval_partition set c_3 = null where id1 = 1;
select * from t_interval_partition;
set enable_opfusion = on;
set enable_partition_opfusion = off;
drop table t_ignore;