fix upsert core and cross-partition upsert

This commit is contained in:
gentle_hu 2021-07-06 14:13:00 +08:00
parent d9dc69168f
commit 4d2c0d708e
14 changed files with 48 additions and 6 deletions

View File

@ -309,6 +309,7 @@ static ModifyTable* _copyModifyTable(const ModifyTable* from)
COPY_NODE_FIELD(updateTlist);
COPY_NODE_FIELD(exclRelTlist);
COPY_SCALAR_FIELD(exclRelRTIndex);
COPY_SCALAR_FIELD(partKeyUpsert);
return newnode;
}
@ -3489,7 +3490,7 @@ static UpsertExpr* _copyUpsertExpr(const UpsertExpr* from)
COPY_NODE_FIELD(updateTlist);
COPY_NODE_FIELD(exclRelTlist);
COPY_SCALAR_FIELD(exclRelIndex);
COPY_SCALAR_FIELD(partKeyUpsert);
return newnode;
}
static CommonTableExpr* _copyCommonTableExpr(const CommonTableExpr* from)

View File

@ -694,7 +694,7 @@ static bool _equalUpsertExpr(const UpsertExpr* a, const UpsertExpr* b)
COMPARE_NODE_FIELD(updateTlist);
COMPARE_NODE_FIELD(exclRelTlist);
COMPARE_SCALAR_FIELD(exclRelIndex);
COMPARE_SCALAR_FIELD(partKeyUpsert);
return true;
}
/*

View File

@ -757,12 +757,14 @@ static void _outModifyTable(StringInfo str, ModifyTable* node)
WRITE_NODE_FIELD(updateTlist);
WRITE_NODE_FIELD(exclRelTlist);
WRITE_INT_FIELD(exclRelRTIndex);
WRITE_BOOL_FIELD(partKeyUpsert);
}
#else
WRITE_ENUM_FIELD(upsertAction, UpsertAction);
WRITE_NODE_FIELD(updateTlist);
WRITE_NODE_FIELD(exclRelTlist);
WRITE_INT_FIELD(exclRelRTIndex);
WRITE_BOOL_FIELD(partKeyUpsert);
#endif
}
@ -782,6 +784,7 @@ static void _outUpsertExpr(StringInfo str, const UpsertExpr* node)
WRITE_NODE_FIELD(updateTlist);
WRITE_NODE_FIELD(exclRelTlist);
WRITE_INT_FIELD(exclRelIndex);
WRITE_BOOL_FIELD(partKeyUpsert);
}
static void _outMergeWhenClause(StringInfo str, const MergeWhenClause* node)
{

View File

@ -3682,7 +3682,7 @@ static ModifyTable* _readModifyTable(ModifyTable* local_node)
IF_EXIST(exclRelRTIndex) {
READ_INT_FIELD(exclRelRTIndex);
}
READ_BOOL_FIELD(partKeyUpsert);
READ_DONE();
}
@ -3694,7 +3694,7 @@ static UpsertExpr* _readUpsertExpr(void)
READ_NODE_FIELD(updateTlist);
READ_NODE_FIELD(exclRelTlist);
READ_INT_FIELD(exclRelIndex);
READ_BOOL_FIELD(partKeyUpsert);
READ_DONE();
}

View File

@ -1845,6 +1845,7 @@ static UpsertExpr* transformUpsertClause(ParseState* pstate, UpsertClause* upser
List* exclRelTlist = NIL;
UpsertAction action = UPSERT_NOTHING;
Relation targetrel = pstate->p_target_relation;
bool partKeyUpsert = false;
#ifdef ENABLE_MULTIPLE_NODES
if (targetrel->rd_rel->relhastriggers) {
@ -1872,7 +1873,6 @@ static UpsertExpr* transformUpsertClause(ParseState* pstate, UpsertClause* upser
* adds have to be reset. markVarForSelectPriv() will add the exact
* required permissions back.
*/
exclRelTlist = BuildExcludedTargetlist(targetrel, exclRelIndex);
exclRte->requiredPerms = 0;
exclRte->selectedCols = NULL;
@ -1886,6 +1886,7 @@ static UpsertExpr* transformUpsertClause(ParseState* pstate, UpsertClause* upser
updateTlist = transformTargetList(pstate, upsertClause->targetList);
updateTlist = transformUpdateTargetList(pstate, updateTlist, upsertClause->targetList, relation);
/* We can't update primary or unique key in upsert, check it here */
#ifdef ENABLE_MULTIPLE_NODES
if (IS_PGXC_COORDINATOR && !u_sess->attr.attr_sql.enable_upsert_to_merge) {
@ -1894,6 +1895,7 @@ static UpsertExpr* transformUpsertClause(ParseState* pstate, UpsertClause* upser
#else
checkUpsertTargetlist(pstate->p_target_relation, updateTlist);
#endif
partKeyUpsert = RELATION_IS_PARTITIONED(targetrel) && targetListHasPartitionKey(updateTlist, targetrel->rd_id);
}
/* Finally, build DUPLICATE KEY UPDATE [NOTHING | ... ] expression */
@ -1902,6 +1904,7 @@ static UpsertExpr* transformUpsertClause(ParseState* pstate, UpsertClause* upser
result->exclRelIndex = exclRelIndex;
result->exclRelTlist = exclRelTlist;
result->upsertAction = action;
result->partKeyUpsert = partKeyUpsert;
return result;
}

View File

@ -8760,6 +8760,7 @@ ModifyTable* make_modifytable(CmdType operation, bool canSetTag, List* resultRel
node->updateTlist = upsertClause->updateTlist;
node->exclRelTlist = upsertClause->exclRelTlist;
node->exclRelRTIndex = upsertClause->exclRelIndex;
node->partKeyUpsert = upsertClause->partKeyUpsert;
} else {
node->upsertAction = UPSERT_NONE;
node->updateTlist = NIL;

View File

@ -1304,6 +1304,11 @@ bool ExecCheckIndexConstraints(TupleTableSlot* slot, EState* estate,
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("INSERT ON DUPLICATE KEY UPDATE does not support deferrable"
" unique constraints/exclusion constraints.")));
/*
* We consider a partitioned table with a global index as a normal table,
* because conflicts can be between multiple partitions.
*/
if (isPartitioned && !RelationIsGlobalIndex(indexRelation)) {
partitionedindexid = RelationGetRelid(indexRelation);
if (!PointerIsValid(partitionIndexOidList)) {

View File

@ -533,7 +533,7 @@ checktest:
*returning = ExecUpdate(conflictTid, oldPartitionOid, bucketid, NULL,
upsertState->us_updateproj, planSlot, &mtstate->mt_epqstate,
mtstate, canSetTag, false);
mtstate, canSetTag, ((ModifyTable*)mtstate->ps.plan)->partKeyUpsert);
ReleaseBuffer(buffer);
return true;
}

View File

@ -432,6 +432,7 @@ typedef struct ModifyTable {
List* updateTlist; /* List of UPDATE target */
List* exclRelTlist; /* target list of the EXECLUDED pseudo relation */
Index exclRelRTIndex; /* RTI of the EXCLUDED pseudo relation */
bool partKeyUpsert;
OpMemInfo mem_info; /* Memory info for modify node */
} ModifyTable;

View File

@ -1398,6 +1398,7 @@ typedef struct UpsertExpr {
List* updateTlist; /* List of UPDATE TargetEntrys */
List* exclRelTlist; /* tlist of the 'EXCLUDED' pseudo relation */
int exclRelIndex; /* RT index of 'EXCLUDED' relation */
bool partKeyUpsert; /* we allow upsert index key and partition key in B_FORMAT */
} UpsertExpr;
#endif /* PRIMNODES_H */

View File

@ -74,6 +74,8 @@ create table pkt (a int primary key, b int, c int);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pkt_pkey" for table "pkt"
create table fkt (a int primary key, b int references pkt, c int);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "fkt_pkey" for table "fkt"
create table up_neg_11(c1 int, c2 int) partition by range(c1)(partition p1 values less than(10), partition p2 values less than(maxvalue));
create unique index index_up_neg_11 on up_neg_11(c2);
-- procedure test
CREATE SCHEMA upsert_test_procedure;
-- explain test

View File

@ -32,6 +32,7 @@ insert into up_neg_07 select a,a,a from generate_series(1,20) as a;
insert into up_neg_08 select a,a,a from generate_series(1,20) as a;
insert into up_neg_09 select a,a,a from generate_series(1,20) as a;
insert into up_neg_10 select a,a,a from generate_series(1,20) as a;
insert into up_neg_11 values(1,1),(2,2),(11,11),(12,12);
-- table cases
---- col table
insert into up_neg_01 values(1,2,3) on duplicate key update c3 = 1;
@ -120,6 +121,22 @@ insert into up_neg_09 values(101, 1, 1) on duplicate key update c2=101;
ERROR: INSERT ON DUPLICATE KEY UPDATE don't allow update on primary key or unique key.
insert into up_neg_09 values(101, 1, 1) on duplicate key update c2 =1,c3=101;
ERROR: INSERT ON DUPLICATE KEY UPDATE don't allow update on primary key or unique key.
---- cross-partition upsert
insert into up_neg_11 values(1, 1) on duplicate key update c1 = 15;
select * from up_neg_11 partition(p1);
c1 | c2
----+----
2 | 2
(1 row)
select * from up_neg_11 partition(p2);
c1 | c2
----+----
11 | 11
12 | 12
15 | 1
(3 rows)
--update unique key mul type plans
EXPLAIN (VERBOSE on, COSTS off) insert into up_neg_10 values(101, 1, 300) on duplicate key update c1=101;
QUERY PLAN

View File

@ -59,6 +59,8 @@ create view up_view as select *from up_neg_01;
create materialized view mat_view as select *from up_neg_01;
create table pkt (a int primary key, b int, c int);
create table fkt (a int primary key, b int references pkt, c int);
create table up_neg_11(c1 int, c2 int) partition by range(c1)(partition p1 values less than(10), partition p2 values less than(maxvalue));
create unique index index_up_neg_11 on up_neg_11(c2);
-- procedure test

View File

@ -33,6 +33,7 @@ insert into up_neg_07 select a,a,a from generate_series(1,20) as a;
insert into up_neg_08 select a,a,a from generate_series(1,20) as a;
insert into up_neg_09 select a,a,a from generate_series(1,20) as a;
insert into up_neg_10 select a,a,a from generate_series(1,20) as a;
insert into up_neg_11 values(1,1),(2,2),(11,11),(12,12);
-- table cases
---- col table
@ -98,6 +99,11 @@ insert into up_neg_09 values(101, 1, 1) on duplicate key update c3=101;
insert into up_neg_09 values(101, 1, 1) on duplicate key update c2=101;
insert into up_neg_09 values(101, 1, 1) on duplicate key update c2 =1,c3=101;
---- cross-partition upsert
insert into up_neg_11 values(1, 1) on duplicate key update c1 = 15;
select * from up_neg_11 partition(p1);
select * from up_neg_11 partition(p2);
--update unique key mul type plans
EXPLAIN (VERBOSE on, COSTS off) insert into up_neg_10 values(101, 1, 300) on duplicate key update c1=101;
insert into up_neg_10 values(101, 1, 300) on duplicate key update c3=101;