Example #1
0
//---------------------------------------------------------------------------
//	@function:
//		CPhysicalDML::PosComputeRequired
//
//	@doc:
//		Compute required sort order based on the key information in the table 
//		descriptor:
//		1. If a table has no keys, no sort order is necessary.
//
//		2. If a table has keys, but they are not modified in the update, no sort
//		order is necessary. This relies on the fact that Split always produces
//		Delete tuples before Insert tuples, so we cannot have two versions of the
//		same tuple on the same time. Consider for example tuple (A: 1, B: 2), where
//		A is key and an update "set B=B+1". Since there cannot be any other tuple 
//		with A=1, and the tuple (1,2) is deleted before tuple (1,3) gets inserted,
//		we don't need to enforce specific order of deletes and inserts.
//
//		3. If the update changes a key column, enforce order on the Action column
//		to deliver Delete tuples before Insert tuples. This is done to avoid a
//		conflict between a newly inserted tuple and an old tuple that is about to be
//		deleted. Consider table with tuples (A: 1),(A: 2), where A is key, and 
//		update "set A=A+1". Split will generate tuples (1,"D"), (2,"I"), (2,"D"), (3,"I").
//		If (2,"I") happens before (2,"D") we will have a violation of the key constraint.
//		Therefore we need to enforce sort order on Action to get all old tuples
//		tuples deleted before the new ones are inserted.
//
//---------------------------------------------------------------------------
COrderSpec *
CPhysicalDML::PosComputeRequired
	(
	IMemoryPool *pmp,
	CTableDescriptor *ptabdesc
	)
{
	COrderSpec *pos = GPOS_NEW(pmp) COrderSpec(pmp);

	const DrgPbs *pdrgpbsKeys = ptabdesc->PdrgpbsKeys();
	if (1 < pdrgpbsKeys->UlLength() && CLogicalDML::EdmlUpdate == m_edmlop)
	{
		// if this is an update on the target table's keys, enforce order on 
		// the action column, see explanation in function's comment		
		const ULONG ulKeySets = pdrgpbsKeys->UlLength();
		BOOL fNeedsSort = false;
		for (ULONG ul = 0; ul < ulKeySets && !fNeedsSort; ul++)
		{
			CBitSet *pbs = (*pdrgpbsKeys)[ul];
			if (!pbs->FDisjoint(m_pbsModified))
			{
				fNeedsSort = true;
				break;
			}
		}
		
		if (fNeedsSort)
		{
			IMDId *pmdid = m_pcrAction->Pmdtype()->PmdidCmp(IMDType::EcmptL);
			pmdid->AddRef();
			pos->Append(pmdid, m_pcrAction, COrderSpec::EntAuto);
		}
	}
	else if (m_ptabdesc->FPartitioned())
	{
		COptimizerConfig *poconf = COptCtxt::PoctxtFromTLS()->Poconf();

		BOOL fInsertSortOnParquet = FInsertSortOnParquet();
		BOOL fInsertSortOnRows = FInsertSortOnRows(poconf);

		if (fInsertSortOnParquet || fInsertSortOnRows)
		{
			GPOS_ASSERT(CLogicalDML::EdmlInsert == m_edmlop);
			m_fInputSorted = true;
			// if this is an INSERT over a partitioned Parquet or Row-oriented table,
			// sort tuples by their table oid
			IMDId *pmdid = m_pcrTableOid->Pmdtype()->PmdidCmp(IMDType::EcmptL);
			pmdid->AddRef();
			pos->Append(pmdid, m_pcrTableOid, COrderSpec::EntAuto);
		}
	}
	
	return pos;
}