//---------------------------------------------------------------------------
//	@function:
//		CJobGroupExploration::FScheduleGroupExpressions
//
//	@doc:
//		Schedule exploration jobs for all unexplored group expressions;
//		the function returns true if it could schedule any new jobs
//
//---------------------------------------------------------------------------
BOOL
CJobGroupExploration::FScheduleGroupExpressions
	(
	CSchedulerContext *psc
	)
{
	CGroupExpression *pgexprLast = m_pgexprLastScheduled;

	// iterate on expressions and schedule them as needed
	CGroupExpression *pgexpr = PgexprFirstUnsched();
	while (NULL != pgexpr)
	{
		if (!pgexpr->FTransitioned(CGroupExpression::estExplored))
		{
			CJobGroupExpressionExploration::ScheduleJob(psc, pgexpr, this);
			pgexprLast = pgexpr;
		}

		// move to next expression
		{
			CGroupProxy gp(m_pgroup);
			pgexpr = gp.PgexprNext(pgexpr);
		}
	}

	BOOL fNewJobs = (m_pgexprLastScheduled != pgexprLast);

	// set last scheduled expression
	m_pgexprLastScheduled = pgexprLast;

	return fNewJobs;
}
Exemple #2
0
//---------------------------------------------------------------------------
//	@function:
//		CGroupProxy::PgexprSkip
//
//	@doc:
//		Skip group expressions starting from the given expression;
//		the type of group expressions to skip is determined by the passed
//		flag
//
//---------------------------------------------------------------------------
CGroupExpression *
CGroupProxy::PgexprSkip
	(
	CGroupExpression *pgexprStart,
	BOOL fSkipLogical
	)
{
	CGroupExpression *pgexpr = pgexprStart;
	while (NULL != pgexpr && fSkipLogical == pgexpr->Pop()->FLogical())
	{
		pgexpr = PgexprNext(pgexpr);
	}

	return pgexpr;
}
//---------------------------------------------------------------------------
//	@function:
//		CGroupExpression::UlHash
//
//	@doc:
//		static hash function for group expressions
//
//---------------------------------------------------------------------------
ULONG
CGroupExpression::UlHash
	(
	const CGroupExpression &gexpr
	)
{
	return gexpr.UlHash();
}
//---------------------------------------------------------------------------
//	@function:
//		CJobGroupOptimization::FScheduleGroupExpressions
//
//	@doc:
//		Schedule optimization jobs for all unoptimized group expressions with
//		the current optimization priority;
//		the function returns true if it could schedule any new jobs
//
//---------------------------------------------------------------------------
BOOL
CJobGroupOptimization::FScheduleGroupExpressions
	(
	CSchedulerContext *psc
	)
{
	CGroupExpression *pgexprLast = m_pgexprLastScheduled;

	// iterate on expressions and schedule them as needed
	CGroupExpression *pgexpr = PgexprFirstUnsched();
	while (NULL != pgexpr)
	{
		// we consider only group expressions matching current optimization level,
		// other group expressions will be optimized when damping current
		// optimization level
		if (psc->Peng()->FOptimizeChild(m_pgexprOrigin, pgexpr, m_poc, EolCurrent()))
		{
			const ULONG ulOptRequests = CPhysical::PopConvert(pgexpr->Pop())->UlOptRequests();
			for (ULONG ul = 0; ul < ulOptRequests; ul++)
			{
				// schedule an optimization job for each request
				CJobGroupExpressionOptimization::ScheduleJob(psc, pgexpr, m_poc, ul, this);
			}
		}
		pgexprLast = pgexpr;

		// move to next expression
		{
			CGroupProxy gp(m_pgroup);
			pgexpr = gp.PgexprSkipLogical(pgexpr);
		}
	}

	BOOL fNewJobs = (m_pgexprLastScheduled != pgexprLast);

	// set last scheduled expression
	m_pgexprLastScheduled = pgexprLast;

	return fNewJobs;
}
Exemple #5
0
//---------------------------------------------------------------------------
//	@function:
//		CCostContext::CCostContext
//
//	@doc:
//		Ctor
//
//---------------------------------------------------------------------------
CCostContext::CCostContext
	(
	IMemoryPool *pmp,
	COptimizationContext *poc,
	ULONG ulOptReq,
	CGroupExpression *pgexpr
	)
	:
	m_pmp(pmp),
	m_cost(GPOPT_INVALID_COST),
	m_estate(estUncosted),
	m_pgexpr(pgexpr),
	m_pgexprForStats(NULL),
	m_pdrgpoc(NULL),
	m_pdpplan(NULL),
	m_ulOptReq(ulOptReq),
	m_fPruned(false),
	m_pstats(NULL),
	m_poc(poc)
{
	GPOS_ASSERT(NULL != poc);
	GPOS_ASSERT(NULL != pgexpr);
	GPOS_ASSERT_IMP
		(
		pgexpr->Pop()->FPhysical(),
		ulOptReq < CPhysical::PopConvert(pgexpr->Pop())->UlOptRequests()
		);

	if (!m_pgexpr->Pop()->FScalar() &&
		!CPhysical::PopConvert(m_pgexpr->Pop())->FPassThruStats())
	{
		CGroupExpression *pgexprForStats = m_pgexpr->Pgroup()->PgexprBestPromise(m_pmp, m_pgexpr);
		if (NULL != pgexprForStats)
		{
			pgexprForStats->AddRef();
			m_pgexprForStats = pgexprForStats;
		}
	}
}
//---------------------------------------------------------------------------
//	@function:
//		CJobTransformation::EevtTransform
//
//	@doc:
//		Apply transformation action
//
//---------------------------------------------------------------------------
CJobTransformation::EEvent
CJobTransformation::EevtTransform
	(
	CSchedulerContext *psc,
	CJob *pjOwner
	)
{
	// get a job pointer
	CJobTransformation *pjt = PjConvert(pjOwner);
	IMemoryPool *pmpGlobal = psc->PmpGlobal();
	IMemoryPool *pmpLocal = psc->PmpLocal();
	CGroupExpression *pgexpr = pjt->m_pgexpr;
	CXform *pxform = pjt->m_pxform;

	// insert transformation results to memo
	CXformResult *pxfres = GPOS_NEW(pmpGlobal) CXformResult(pmpGlobal);
	ULONG ulElapsedTime = 0;
	pgexpr->Transform(pmpGlobal, pmpLocal, pxform, pxfres, &ulElapsedTime);
	psc->Peng()->InsertXformResult(pgexpr->Pgroup(), pxfres, pxform->Exfid(), pgexpr, ulElapsedTime);
	pxfres->Release();

	return eevCompleted;
}
//---------------------------------------------------------------------------
//	@function:
//		CExpressionHandle::DeriveProducerStats
//
//	@doc:
//		If the child (ulChildIndex) is a CTE consumer, then derive is corresponding
//		producer statistics.
//
//---------------------------------------------------------------------------
void
CExpressionHandle::DeriveProducerStats
	(
	ULONG ulChildIndex,
	CColRefSet *pcrsStats
	)
{
	// check to see if there are any CTE consumers in the group whose properties have
	// to be pushed to its corresponding CTE producer
	CGroupExpression *pgexpr = Pgexpr();
	if (NULL != pgexpr)
	{
		CGroup *pgroupChild = (*pgexpr)[ulChildIndex];
		if (pgroupChild->FHasAnyCTEConsumer())
		{
			CGroupExpression *pgexprCTEConsumer = pgroupChild->PgexprAnyCTEConsumer();
			CLogicalCTEConsumer *popConsumer = CLogicalCTEConsumer::PopConvert(pgexprCTEConsumer->Pop());
			COptCtxt::PoctxtFromTLS()->Pcteinfo()->DeriveProducerStats(popConsumer, pcrsStats);
		}

		return;
	}

	// statistics are also derived on expressions representing the producer that may have
	// multiple CTE consumers. We should ensure that their properties are to pushed to their
	// corresponding CTE producer
	CExpression *pexpr = Pexpr();
	if (NULL != pexpr)
	{
		CExpression *pexprChild = (*pexpr)[ulChildIndex];
		if (COperator::EopLogicalCTEConsumer == pexprChild->Pop()->Eopid())
		{
			CLogicalCTEConsumer *popConsumer = CLogicalCTEConsumer::PopConvert(pexprChild->Pop());
			COptCtxt::PoctxtFromTLS()->Pcteinfo()->DeriveProducerStats(popConsumer, pcrsStats);
		}
	}
}
//---------------------------------------------------------------------------
//	@function:
//		CExpressionHandle::PexprScalarChild
//
//	@doc:
//		Get the scalar child at given index
//
//---------------------------------------------------------------------------
CExpression *
CExpressionHandle::PexprScalarChild
	(
	ULONG ulChildIndex
	)
	const
{
	GPOS_ASSERT(ulChildIndex < UlArity());

	if (NULL != m_pgexpr)
	{
		// access scalar expression cached on the child scalar group
		GPOS_ASSERT((*m_pgexpr)[ulChildIndex]->FScalar());

		CExpression *pexprScalar = (*m_pgexpr)[ulChildIndex]->PexprScalar();
		GPOS_ASSERT_IMP(NULL == pexprScalar, CDrvdPropScalar::Pdpscalar((*m_pgexpr)[ulChildIndex]->Pdp())->FHasSubquery());

		return pexprScalar;
	}

	if (NULL != m_pexpr && NULL != (*m_pexpr)[ulChildIndex]->Pgexpr())
	{
		// if the expression does not come from a group, but its child does then
		// get the scalar child from that group
		CGroupExpression *pgexpr = (*m_pexpr)[ulChildIndex]->Pgexpr();
		CExpression *pexprScalar = pgexpr->Pgroup()->PexprScalar();
		GPOS_ASSERT_IMP(NULL == pexprScalar, CDrvdPropScalar::Pdpscalar((*m_pexpr)[ulChildIndex]->PdpDerive())->FHasSubquery());

		return pexprScalar;
	}

	// access scalar expression from the child expression node
	GPOS_ASSERT((*m_pexpr)[ulChildIndex]->Pop()->FScalar());

	return (*m_pexpr)[ulChildIndex];
}
//---------------------------------------------------------------------------
//	@function:
//		COptimizationContext::PrppCTEProducer
//
//	@doc:
//		Compute required properties to CTE producer based on plan properties
//		of CTE consumer
//
//---------------------------------------------------------------------------
CReqdPropPlan *
COptimizationContext::PrppCTEProducer
	(
	IMemoryPool *mp,
	COptimizationContext *poc,
	ULONG ulSearchStages
	)
{
	GPOS_ASSERT(NULL != poc);
	GPOS_ASSERT(NULL != poc->PccBest());

	CCostContext *pccBest = poc->PccBest();
	CGroupExpression *pgexpr = pccBest->Pgexpr();
	BOOL fOptimizeCTESequence =
			(
			COperator::EopPhysicalSequence == pgexpr->Pop()->Eopid() &&
			(*pgexpr)[0]->FHasCTEProducer()
			);

	if (!fOptimizeCTESequence)
	{
		// best group expression is not a CTE sequence
		return NULL;
	}

	COptimizationContext *pocProducer = (*pgexpr)[0]->PocLookupBest(mp, ulSearchStages, (*pccBest->Pdrgpoc())[0]->Prpp());
	if (NULL == pocProducer)
	{
		return NULL;
	}

	CCostContext *pccProducer = pocProducer->PccBest();
	if (NULL == pccProducer)
	{
		return NULL;
	}
	COptimizationContext *pocConsumer = (*pgexpr)[1]->PocLookupBest(mp, ulSearchStages, (*pccBest->Pdrgpoc())[1]->Prpp());
	if (NULL == pocConsumer)
	{
		return NULL;
	}

	CCostContext *pccConsumer = pocConsumer->PccBest();
	if (NULL == pccConsumer)
	{
		return NULL;
	}

	CColRefSet *pcrsInnerOutput = CDrvdPropRelational::GetRelationalProperties((*pgexpr)[1]->Pdp())->PcrsOutput();
	CPhysicalCTEProducer *popProducer = CPhysicalCTEProducer::PopConvert(pccProducer->Pgexpr()->Pop());
	UlongToColRefMap *colref_mapping = COptCtxt::PoctxtFromTLS()->Pcteinfo()->PhmulcrConsumerToProducer(mp, popProducer->UlCTEId(), pcrsInnerOutput, popProducer->Pdrgpcr());
	CReqdPropPlan *prppProducer = CReqdPropPlan::PrppRemap(mp, pocProducer->Prpp(), pccConsumer->Pdpplan(), colref_mapping);
	colref_mapping->Release();

	if (prppProducer->Equals(pocProducer->Prpp()))
	{
		prppProducer->Release();

		return NULL;
	}

	return prppProducer;
}