Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/backend/executor/nodeDML.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ ExecDML(DMLState *node)
{
return NULL;
}
EvalPlanQualSetSlot(&node->dml_epqstate, slot);

bool isnull = false;
int action = DatumGetUInt32(slot_getattr(slot, plannode->actionColIdx, &isnull));
Expand Down Expand Up @@ -145,7 +146,7 @@ ExecDML(DMLState *node)
segid,
NULL, /* GPDB_91_MERGE_FIXME: oldTuple? */
node->cleanedUpSlot,
NULL /* DestReceiver */,
&node->dml_epqstate,
node->ps.state,
!isUpdate, /* GPDB_91_MERGE_FIXME: where to get canSetTag? */
PLANGEN_OPTIMIZER /* Plan origin */,
Expand Down Expand Up @@ -177,13 +178,16 @@ ExecInitDML(DML *node, EState *estate, int eflags)
CmdType operation = estate->es_plannedstmt->commandType;
ResultRelInfo *resultRelInfo = estate->es_result_relation_info;

EvalPlanQualInit(&dmlstate->dml_epqstate, NULL, NULL, NIL, node->epqParam);

ExecInitResultTupleSlot(estate, &dmlstate->ps);

dmlstate->ps.targetlist = (List *)
ExecInitExpr((Expr *) node->plan.targetlist,
(PlanState *) dmlstate);

Plan *outerPlan = outerPlan(node);
EvalPlanQualSetPlan(&dmlstate->dml_epqstate, outerPlan, NULL);
outerPlanState(dmlstate) = ExecInitNode(outerPlan, estate, eflags);

/*
Expand Down Expand Up @@ -279,6 +283,7 @@ ExecEndDML(DMLState *node)
ExecFreeExprContext(&node->ps);
ExecClearTuple(node->ps.ps_ResultTupleSlot);
ExecClearTuple(node->cleanedUpSlot);
EvalPlanQualEnd(&node->dml_epqstate);
ExecEndNode(outerPlanState(node));
EndPlanStateGpmonPkt(&node->ps);
}
Expand Down
11 changes: 0 additions & 11 deletions src/backend/executor/nodeModifyTable.c
Original file line number Diff line number Diff line change
Expand Up @@ -961,17 +961,6 @@ ldelete:;
{
TupleTableSlot *epqslot;

/*
* TODO: DML node doesn't initialize `epqstate` parameter so
* we exclude EPQ routine for this type of modification and
* act as in RR and upper isolation levels.
*/
if (!epqstate)
ereport(ERROR,
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
errmsg("could not serialize access due to concurrent update"),
errhint("Use PostgreSQL Planner instead of Optimizer for this query via optimizer=off GUC setting")));

epqslot = EvalPlanQual(estate,
epqstate,
resultRelationDesc,
Expand Down
77 changes: 77 additions & 0 deletions src/backend/gpopt/translate/CContextDXLToPlStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ CContextDXLToPlStmt::CContextDXLToPlStmt(
{
m_cte_consumer_info = GPOS_NEW(m_mp) HMUlCTEConsumerInfo(m_mp);
m_num_partition_selectors_array = GPOS_NEW(m_mp) ULongPtrArray(m_mp);
m_used_rte_indexes = GPOS_NEW(m_mp) HMUlIndex(m_mp);
}

//---------------------------------------------------------------------------
Expand All @@ -74,6 +75,7 @@ CContextDXLToPlStmt::~CContextDXLToPlStmt()
{
m_cte_consumer_info->Release();
m_num_partition_selectors_array->Release();
m_used_rte_indexes->Release();
}

//---------------------------------------------------------------------------
Expand Down Expand Up @@ -462,4 +464,79 @@ CContextDXLToPlStmt::GetDistributionHashFuncForType(Oid typid)
return hashproc;
}

RangeTblEntry *
CContextDXLToPlStmt::GetRTEByIndex(Index index)
{
return (RangeTblEntry *) gpdb::ListNth(*(m_rtable_entries_list),
int(index - 1));
}

//---------------------------------------------------------------------------
// @function: of associated
// CContextDXLToPlStmt::GetRTEIndexByTableDescr
//
// @doc:
//
// For given table descriptor this function returns index of rte in
// m_rtable_entries_list for furhter processing and set a flag that
// rte was processed.
// In case of DML operations there is more than one table descr pointing
// to the result relation and to detect position of already processed rte
// `assigned_query_id_for_target_rel` of table descriptor is used.
//---------------------------------------------------------------------------
Index
CContextDXLToPlStmt::GetRTEIndexByTableDescr(const CDXLTableDescr *table_descr,
BOOL *is_rte_exists)
{
*is_rte_exists = false;

// `assigned_query_id_for_target_rel` is a "tag" of table descriptors, it
// shows id of query structure which contains result relation. If table
// descriptors have the same `assigned_query_id_for_target_rel` - these
// table descriptors point to the same result relation in `ModifyTable`
// operation. It's not zero (0) value (which equal to `UNASSIGNED_QUERYID`
// define) if: user query is a INSERT/UPDATE/DELETE (`ModifyTable`
// operation) and this table descriptor points to the result relation of
// operation, for ex.:
// ```sql
// create table b (i int, j int);
// create table c (i int);
// insert into b(i,j) values (1,2), (2,3), (3,4);
// insert into c(i) values (1), (2);
// delete from b where i in (select i from c);
// ```
// where `b` is a result relation (table descriptors pointing to it
// will have the same `assigned_query_id_for_target_rel` > 0), and
// `c` is not (all table descriptors which points to `c` will have
// `assigned_query_id_for_target_rel`=0 (equal to `UNASSIGNED_QUERYID`)
ULONG assigned_query_id_for_target_rel =
table_descr->GetAssignedQueryIdForTargetRel();
if (assigned_query_id_for_target_rel == UNASSIGNED_QUERYID)
{
return gpdb::ListLength(*(m_rtable_entries_list)) + 1;
}

Index *usedIndex =
m_used_rte_indexes->Find(&assigned_query_id_for_target_rel);

// `usedIndex` is a non NULL value in next case: table descriptor with
// the same `assigned_query_id_for_target_rel` was processed previously
// (so no need to create a new index for result relation like the relation
// itself)
if (usedIndex)
{
*is_rte_exists = true;
return *usedIndex;
}

// `assigned_query_id_for_target_rel` of table descriptor which points to
// result relation wasn't previously processed - create a new index.
Index new_index = gpdb::ListLength(*(m_rtable_entries_list)) + 1;
m_used_rte_indexes->Insert(GPOS_NEW(m_mp)
ULONG(assigned_query_id_for_target_rel),
GPOS_NEW(m_mp) Index(new_index));

return new_index;
}

// EOF
8 changes: 8 additions & 0 deletions src/backend/gpopt/translate/CContextQueryToDXL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,19 @@ CContextQueryToDXL::CContextQueryToDXL(CMemoryPool *mp)
{
// map that stores gpdb att to optimizer col mapping
m_colid_counter = GPOS_NEW(mp) CIdGenerator(GPDXL_COL_ID_START);
m_queryid_counter = GPOS_NEW(mp) CIdGenerator(GPDXL_QUERY_ID_START);
m_cte_id_counter = GPOS_NEW(mp) CIdGenerator(GPDXL_CTE_ID_START);
}

CContextQueryToDXL::~CContextQueryToDXL()
{
GPOS_DELETE(m_queryid_counter);
GPOS_DELETE(m_colid_counter);
GPOS_DELETE(m_cte_id_counter);
}

ULONG
CContextQueryToDXL::GetNextQueryId()
{
return m_queryid_counter->next_id();
}
Loading