//---------------------------------------------------------------------------
//	@function:
//		CExpressionHandle::CopyCostCtxtProps
//
//	@doc:
//		Cache plan properties of cost context and its children on the handle
//
//---------------------------------------------------------------------------
void
CExpressionHandle::CopyCostCtxtProps()
{
	GPOS_ASSERT(NULL != m_pcc);
	GPOS_ASSERT(NULL == m_pdrgpdp);
	GPOS_ASSERT(NULL == m_pdp);

	// add-ref context properties
	CDrvdProp *pdp = m_pcc->Pdpplan();
	pdp->AddRef();
	m_pdp = pdp;

	// add-ref child group expressions' properties
	const ULONG ulArity = UlArity();
	m_pdrgpdp = GPOS_NEW(m_pmp) DrgPdp(m_pmp, ulArity);
	for (ULONG ul = 0; ul < ulArity; ul++)
	{
		CGroup *pgroupChild = (*m_pgexpr)[ul];
		if (!pgroupChild->FScalar())
		{
			COptimizationContext *pocChild = (*m_pcc->Pdrgpoc())[ul];
			GPOS_ASSERT(NULL != pocChild);

			CCostContext *pccChild = pocChild->PccBest();
			GPOS_ASSERT(NULL != pccChild);

			pdp = pccChild->Pdpplan();
			pdp->AddRef();
			m_pdrgpdp->Append(pdp);
		}
	}
}
//---------------------------------------------------------------------------
//	@function:
//		CLogicalInnerJoin::FFewerConj
//
//	@doc:
//		Compare two innerJoin group expressions, test whether the first one
//		has less join predicates than the second one. This is used to
//		prioritize innerJoin with less predicates for stats derivation
//
//---------------------------------------------------------------------------
BOOL
CLogicalInnerJoin::FFewerConj
	(
	IMemoryPool *pmp,
	CGroupExpression *pgexprFst,
	CGroupExpression *pgexprSnd
	)
{
	if (NULL == pgexprFst || NULL == pgexprSnd)
	{
		return false;
	}

	if (COperator::EopLogicalInnerJoin != pgexprFst->Pop()->Eopid() ||
		COperator::EopLogicalInnerJoin != pgexprSnd->Pop()->Eopid())
	{
		return false;
	}

	// third child must be the group for join conditions
	CGroup *pgroupScalarFst = (*pgexprFst)[2];
	CGroup *pgroupScalarSnd = (*pgexprSnd)[2];
	GPOS_ASSERT(pgroupScalarFst->FScalar());
	GPOS_ASSERT(pgroupScalarSnd->FScalar());

	DrgPexpr *pdrgpexprConjFst = CPredicateUtils::PdrgpexprConjuncts(pmp, pgroupScalarFst->PexprScalar());
	DrgPexpr *pdrgpexprConjSnd = CPredicateUtils::PdrgpexprConjuncts(pmp, pgroupScalarSnd->PexprScalar());

	ULONG ulConjFst = pdrgpexprConjFst->UlLength();
	ULONG ulConjSnd = pdrgpexprConjSnd->UlLength();

	pdrgpexprConjFst->Release();
	pdrgpexprConjSnd->Release();

	return ulConjFst < ulConjSnd;
}