Skip to content

Commit

Permalink
6X specific changes
Browse files Browse the repository at this point in the history
  • Loading branch information
KnightMurloc committed Sep 4, 2023
1 parent f262185 commit 20e1c18
Show file tree
Hide file tree
Showing 11 changed files with 115 additions and 100 deletions.
42 changes: 32 additions & 10 deletions src/backend/executor/nodeDML.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,20 +57,19 @@ ExecDML(DMLState *node)
{
return NULL;
}
EvalPlanQualSetSlot(&node->mt_epqstate, slot);

bool isnull = false;
int action = DatumGetUInt32(slot_getattr(slot, plannode->actionColIdx, &isnull));
Assert(!isnull);
int action = -1;
bool isUpdate = node->ps.state->es_plannedstmt->commandType == CMD_UPDATE;

bool isUpdate = false;
if (node->ps.state->es_plannedstmt->commandType == CMD_UPDATE)
// if it's not in place update
if(plannode->actionColIdx)
{
isUpdate = true;
action = DatumGetUInt32(slot_getattr(slot, plannode->actionColIdx, &isnull));
Assert(!isnull);
}

Assert(action == DML_INSERT || action == DML_DELETE);


/*
* Reset per-tuple memory context to free any expression evaluation
* storage allocated in the previous tuple cycle.
Expand Down Expand Up @@ -123,7 +122,7 @@ ExecDML(DMLState *node)
isUpdate,
InvalidOid);
}
else /* DML_DELETE */
else if(DML_DELETE == action)
{
int32 segid = GpIdentity.segindex;
Datum ctid = slot_getattr(slot, plannode->ctidColIdx, &isnull);
Expand Down Expand Up @@ -151,6 +150,26 @@ ExecDML(DMLState *node)
PLANGEN_OPTIMIZER /* Plan origin */,
isUpdate);
}
else /* in place update */
{
int32 segid = GpIdentity.segindex;

Datum ctid = slot_getattr(slot, plannode->ctidColIdx, &isnull);

ItemPointer tupleid = (ItemPointer) DatumGetPointer(ctid);
ItemPointerData tuple_ctid = *tupleid;
tupleid = &tuple_ctid;

ExecUpdate(
tupleid,
segid,
NULL, //oldtuple
node->cleanedUpSlot,
NULL, //planSlot
&node->mt_epqstate,
node->ps.state,
true);
}

return slot;
}
Expand Down Expand Up @@ -186,6 +205,8 @@ ExecInitDML(DML *node, EState *estate, int eflags)
Plan *outerPlan = outerPlan(node);
outerPlanState(dmlstate) = ExecInitNode(outerPlan, estate, eflags);

EvalPlanQualInit(&dmlstate->mt_epqstate, estate, outerPlan, NIL, 0);

/*
* ORCA Plan does not seem to set junk attribute for "gp_segment_id", else we
* could call the simple code below.
Expand Down Expand Up @@ -229,7 +250,7 @@ ExecInitDML(DML *node, EState *estate, int eflags)
dmlstate->junkfilter = ExecInitJunkFilter(node->plan.targetlist,
dmlstate->ps.state->es_result_relation_info->ri_RelationDesc->rd_att->tdhasoid,
dmlstate->cleanedUpSlot);

estate->es_result_relation_info->ri_junkFilter = dmlstate->junkfilter;
/*
* We don't maintain typmod in the targetlist, so we should fixup the
* junkfilter to use the same tuple descriptor as the result relation.
Expand Down Expand Up @@ -279,6 +300,7 @@ ExecEndDML(DMLState *node)
ExecFreeExprContext(&node->ps);
ExecClearTuple(node->ps.ps_ResultTupleSlot);
ExecClearTuple(node->cleanedUpSlot);
EvalPlanQualEnd(&node->mt_epqstate);
ExecEndNode(outerPlanState(node));
EndPlanStateGpmonPkt(&node->ps);
}
Expand Down
1 change: 0 additions & 1 deletion src/backend/gpopt/gpopt.mk
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
override CPPFLAGS := -std=c++98 $(CPPFLAGS)
override CPPFLAGS := -I$(top_builddir)/src/backend/gporca/libgpos/include $(CPPFLAGS)
override CPPFLAGS := -I$(top_builddir)/src/backend/gporca/libgpopt/include $(CPPFLAGS)
override CPPFLAGS := -I$(top_builddir)/src/backend/gporca/libnaucrates/include $(CPPFLAGS)
Expand Down
25 changes: 18 additions & 7 deletions src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4084,6 +4084,7 @@ CTranslatorDXLToPlStmt::TranslateDXLDml(
DML *dml = MakeNode(DML);
Plan *plan = &(dml->plan);
AclMode acl_mode = ACL_NO_RIGHTS;
BOOL isSplit = phy_dml_dxlop->FSplit();

switch (phy_dml_dxlop->GetDmlOpType())
{
Expand Down Expand Up @@ -4170,14 +4171,26 @@ CTranslatorDXLToPlStmt::TranslateDXLDml(
dml_target_list = target_list_with_dropped_cols;
}

// Extract column numbers of the action and ctid columns from the
// target list.
dml->actionColIdx = AddTargetEntryForColId(&dml_target_list, &child_context,
phy_dml_dxlop->ActionColId(),
true /*is_resjunk*/);

dml->ctidColIdx = AddTargetEntryForColId(&dml_target_list, &child_context,
phy_dml_dxlop->GetCtIdColId(),
true /*is_resjunk*/);

// Doesn't needed for in place update
if (isSplit || CMD_UPDATE != m_cmd_type)
{
// Extract column numbers of the action and ctid columns from the
// target list.
dml->actionColIdx = AddTargetEntryForColId(
&dml_target_list, &child_context, phy_dml_dxlop->ActionColId(),
true /*is_resjunk*/);
GPOS_ASSERT(0 != dml->actionColIdx);
}
else
{
dml->actionColIdx = 0;
}

if (phy_dml_dxlop->IsOidsPreserved())
{
dml->tupleoidColIdx = AddTargetEntryForColId(
Expand All @@ -4189,8 +4202,6 @@ CTranslatorDXLToPlStmt::TranslateDXLDml(
dml->tupleoidColIdx = 0;
}

GPOS_ASSERT(0 != dml->actionColIdx);

plan->targetlist = dml_target_list;

plan->lefttree = child_plan;
Expand Down
1 change: 0 additions & 1 deletion src/backend/gporca/gporca.mk
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,3 @@ override CPPFLAGS := -I$(top_builddir)/src/backend/gporca/libgpdbcost/include $(
# Do not omit frame pointer. Even with RELEASE builds, it is used for
# backtracing.
override CPPFLAGS := -Werror -Wextra -Wpedantic -Wno-variadic-macros -fno-omit-frame-pointer $(CPPFLAGS)
override CPPFLAGS := -std=gnu++98 $(CPPFLAGS)
Original file line number Diff line number Diff line change
Expand Up @@ -3300,6 +3300,12 @@ CExpressionPreprocessor::ConvertSplitUpdateToInPlaceUpdate(CMemoryPool *mp,
const ULongPtrArray *pdrgpulPart = tabdesc->PdrgpulPart();
const ULONG ulPartKeys = pdrgpulPart->Size();

if (tabdesc->GetRelDistribution() ==
IMDRelation::Ereldistrpolicy::EreldistrRandom)
{
split_update = true;
}

// Uses split update if any of the modified columns are either
// distribution or partition keys.
// FIXME: Tested on distribution columns. Validate this after DML on
Expand All @@ -3315,9 +3321,10 @@ CExpressionPreprocessor::ConvertSplitUpdateToInPlaceUpdate(CMemoryPool *mp,
{
CColRef *pcrInsert = (*pdrgpcrInsert)[ul];
CColRef *pcrDelete = (*pdrgpcrDelete)[ul];

// Checking if column is either distribution or partition key.
if (pcrInsert != pcrDelete &&
(pcrDelete->IsDistCol() || ppartColRefs->Find(pcrInsert) != NULL))
if ((pcrInsert != pcrDelete && pcrDelete->IsDistCol()) ||
(ppartColRefs->Find(pcrInsert) != NULL))
{
split_update = true;
break;
Expand Down
24 changes: 2 additions & 22 deletions src/backend/gporca/libgpopt/src/xforms/CXformUpdate2DML.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,26 +151,6 @@ CXformUpdate2DML::Transform(CXformContext *pxfctxt, CXformResult *pxfres,
pexprAssertConstraints = pexprSplit;
}

// generate oid column and project operator
CExpression *pexprProject = NULL;
if (ptabdesc->IsPartitioned())
{
// generate a partition selector
pexprProject = CXformUtils::PexprLogicalPartitionSelector(
mp, ptabdesc, pdrgpcrInsert, pexprAssertConstraints);
}
else
{
// generate a project operator
IMDId *pmdidTable = ptabdesc->MDId();

OID oidTable = CMDIdGPDB::CastMdid(pmdidTable)->Oid();
CExpression *pexprOid = CUtils::PexprScalarConstOid(mp, oidTable);

pexprProject =
CUtils::PexprAddProjection(mp, pexprAssertConstraints, pexprOid);
}

const ULONG num_cols = pdrgpcrInsert->Size();

CExpression *pexprDML = NULL;
Expand Down Expand Up @@ -199,7 +179,7 @@ CXformUpdate2DML::Transform(CXformContext *pxfctxt, CXformResult *pxfres,
CLogicalDML(mp, CLogicalDML::EdmlUpdate, ptabdesc,
pdrgpcrDelete, pbsModified, pcrAction, pcrCtid,
pcrSegmentId, pcrTupleOid, fSplit),
pexprProject);
pexprAssertConstraints);
}
else
{
Expand All @@ -210,7 +190,7 @@ CXformUpdate2DML::Transform(CXformContext *pxfctxt, CXformResult *pxfres,
CLogicalDML(mp, CLogicalDML::EdmlUpdate, ptabdesc,
pdrgpcrInsert, GPOS_NEW(mp) CBitSet(mp), pcrAction,
pcrCtid, pcrSegmentId, NULL, fSplit),
pexprProject);
pexprAssertConstraints);
}

// TODO: - Oct 30, 2012; detect and handle AFTER triggers on update
Expand Down
1 change: 1 addition & 0 deletions src/include/nodes/execnodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -2831,6 +2831,7 @@ typedef struct DMLState
JunkFilter *junkfilter; /* filter that removes junk and dropped attributes */
TupleTableSlot *cleanedUpSlot; /* holds 'final' tuple which matches the target relation schema */
AttrNumber segid_attno; /* attribute number of "gp_segment_id" */
EPQState mt_epqstate; /* for evaluating EvalPlanQual rechecks */
} DMLState;

/*
Expand Down
33 changes: 16 additions & 17 deletions src/test/isolation2/expected/gdd/concurrent_update_optimizer.out
Original file line number Diff line number Diff line change
Expand Up @@ -353,29 +353,28 @@ UPDATE 1
-- make sure planner will contain InitPlan
-- NOTE: orca does not generate InitPlan.
2: explain update t_epq_subplans set b = b + 1 where a > -1.5 * (select max(a) from t_epq_subplans);
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------
Update (cost=0.00..1324032.68 rows=1 width=1)
-> Split (cost=0.00..1324032.61 rows=1 width=22)
-> Result (cost=0.00..1324032.61 rows=1 width=22)
-> Seq Scan on t_epq_subplans (cost=0.00..1324032.61 rows=1 width=18)
Filter: ((a)::numeric > ((-1.5) * ((SubPlan 1))::numeric))
SubPlan 1 (slice0; segments: 3)
-> Materialize (cost=0.00..431.00 rows=1 width=4)
-> Broadcast Motion 1:3 (slice2; segments: 1) (cost=0.00..431.00 rows=3 width=4)
-> Aggregate (cost=0.00..431.00 rows=1 width=4)
-> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=4)
-> Aggregate (cost=0.00..431.00 rows=1 width=4)
-> Seq Scan on t_epq_subplans t_epq_subplans_1 (cost=0.00..431.00 rows=1 width=4)
Optimizer: Pivotal Optimizer (GPORCA)
(14 rows)
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------
Update (cost=0.00..1324032.63 rows=1 width=1)
-> Result (cost=0.00..1324032.61 rows=1 width=18)
-> Seq Scan on t_epq_subplans (cost=0.00..1324032.61 rows=1 width=18)
Filter: ((a)::numeric > ('-1.5'::numeric * ((SubPlan 1))::numeric))
SubPlan 1 (slice0; segments: 3)
-> Materialize (cost=0.00..431.00 rows=1 width=4)
-> Broadcast Motion 1:3 (slice2; segments: 1) (cost=0.00..431.00 rows=3 width=4)
-> Aggregate (cost=0.00..431.00 rows=1 width=4)
-> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=4)
-> Aggregate (cost=0.00..431.00 rows=1 width=4)
-> Seq Scan on t_epq_subplans t_epq_subplans_1 (cost=0.00..431.00 rows=1 width=4)
Optimizer: Pivotal Optimizer (GPORCA)
(12 rows)
2&: update t_epq_subplans set b = b + 1 where a > -1.5 * (select max(a) from t_epq_subplans); <waiting ...>

1: end;
END
-- session 2 should throw error and not PANIC
2<: <... completed>
ERROR: tuple to be updated was already moved to another segment due to concurrent update (seg1 127.0.1.1:6003 pid=116712)
ERROR: EvalPlanQual can not handle subPlan with Motion node (seg1 172.17.0.2:7003 pid=808)

1: drop table t_epq_subplans;
DROP
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,25 +107,24 @@ ABORT
-- TODO: this case is for planner, it will not error out on 6X now,
-- because 6x does not remove explicit motion yet.
explain (costs off) update tab1 set a = 999 from tab2, tab3 where tab1.a = tab2.a and tab1.b = tab3.b;
QUERY PLAN
---------------------------------------------------------------------------------
Update
-> Redistribute Motion 3:3 (slice2; segments: 3)
Hash Key: tab1.b
-> Split
-> Result
-> Hash Join
Hash Cond: (tab2.a = tab1.a)
-> Seq Scan on tab2
-> Hash
-> Broadcast Motion 3:3 (slice1; segments: 3)
-> Hash Join
Hash Cond: (tab3.b = tab1.b)
-> Seq Scan on tab3
-> Hash
-> Seq Scan on tab1
Optimizer: Pivotal Optimizer (GPORCA)
(16 rows)
QUERY PLAN
---------------------------------------------------------------------------
Update
-> Result
-> Redistribute Motion 3:3 (slice2; segments: 3)
Hash Key: tab1.b
-> Hash Join
Hash Cond: (tab2.a = tab1.a)
-> Seq Scan on tab2
-> Hash
-> Broadcast Motion 3:3 (slice1; segments: 3)
-> Hash Join
Hash Cond: (tab3.b = tab1.b)
-> Seq Scan on tab3
-> Hash
-> Seq Scan on tab1
Optimizer: Pivotal Optimizer (GPORCA)
(15 rows)
begin;
BEGIN
update tab1 set a = 999 from tab2, tab3 where tab1.a = tab2.a and tab1.b = tab3.b;
Expand Down Expand Up @@ -165,28 +164,26 @@ ABORT
explain (costs off) update tab1 set a = 999 from tab2, tab3 where tab1.a = tab2.a and tab1.b = tab3.a;
QUERY PLAN
---------------------------------------------------------------------------------------------------
Update
-> Redistribute Motion 3:3 (slice3; segments: 3)
Hash Key: tab1.b
-> Split
-> Result
-> Hash Join
Hash Cond: (tab3.a = tab1.b)
-> Seq Scan on tab3
-> Hash
-> Broadcast Motion 3:3 (slice2; segments: 3)
-> Hash Join
Hash Cond: (tab2.a = tab1.a)
-> Seq Scan on tab2
-> Hash
-> Broadcast Motion 3:3 (slice1; segments: 3)
-> Seq Scan on tab1
Update
-> Result
-> Redistribute Motion 3:3 (slice3; segments: 3)
Hash Key: tab1.b
-> Hash Join
-> Seq Scan on tab3
-> Hash
-> Broadcast Motion 3:3 (slice2; segments: 3)
-> Hash Join
Hash Cond: (tab2.a = tab1.a)
-> Seq Scan on tab2
-> Hash
-> Broadcast Motion 3:3 (slice1; segments: 3)
-> Seq Scan on tab1
Optimizer: Pivotal Optimizer (GPORCA)
(17 rows)
(16 rows)
begin;
BEGIN
update tab1 set a = 999 from tab2, tab3 where tab1.a = tab2.a and tab1.b = tab3.a;
ERROR: distribution key of the tuple (0, 1) doesn't belong to current segment (actually from seg0) (nodeModifyTable.c:602) (seg1 127.0.1.1:6003 pid=78344) (nodeModifyTable.c:602)
UPDATE 1
abort;
ABORT

Expand Down
4 changes: 2 additions & 2 deletions src/test/regress/expected/gporca_optimizer.out
Original file line number Diff line number Diff line change
Expand Up @@ -13733,7 +13733,7 @@ and first_id in (select first_id from mat_w);
Output: share0_ref2.first_id
Optimizer: Pivotal Optimizer (GPORCA)
Settings: optimizer=on
(30 rows)
(31 rows)

with mat_w as (
select first_id
Expand Down Expand Up @@ -14686,7 +14686,7 @@ update window_agg_test t
set i = tt.i
from (select (min(i) over (order by j)) as i, j from window_agg_test) tt
where t.j = tt.j;
QUERY PLAN
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------
Update (cost=0.00..862.02 rows=1 width=1)
-> Explicit Redistribute Motion 1:3 (slice3; segments: 1) (cost=0.00..862.00 rows=1 width=18)
Expand Down
2 changes: 1 addition & 1 deletion src/test/regress/expected/qp_dml_joins_optimizer.out
Original file line number Diff line number Diff line change
Expand Up @@ -4080,7 +4080,7 @@ UPDATE dml_heap_v SET a = dml_heap_u.a FROM dml_heap_u WHERE dml_heap_u.b = dml_
SELECT SUM(a) FROM dml_heap_v;
sum
-----
63
55
(1 row)

--Update with joins on multiple table
Expand Down

0 comments on commit 20e1c18

Please sign in to comment.