コード例 #1
0
ファイル: CXformTest.cpp プロジェクト: HanumathRao/gporca
//---------------------------------------------------------------------------
//	@function:
//		CXformTest::PexprStarJoinTree
//
//	@doc:
//		Generate a randomized star join tree
//
//---------------------------------------------------------------------------
CExpression *
CXformTest::PexprStarJoinTree
	(
	IMemoryPool *pmp,
	ULONG ulTabs
	)
{
	
	CExpression *pexprLeft = CTestUtils::PexprLogicalGet(pmp);
	
	for (ULONG ul = 1; ul < ulTabs; ul++)
	{
		CDrvdPropRelational *pdprelLeft = CDrvdPropRelational::Pdprel(pexprLeft->PdpDerive());
		CColRef *pcrLeft = pdprelLeft->PcrsOutput()->PcrAny();
	
		CExpression *pexprRight = CTestUtils::PexprLogicalGet(pmp);

		CDrvdPropRelational *pdprelRight = CDrvdPropRelational::Pdprel(pexprRight->PdpDerive());
		CColRef *pcrRight = pdprelRight->PcrsOutput()->PcrAny();
		
		CExpression *pexprPred = CUtils::PexprScalarEqCmp(pmp, pcrLeft, pcrRight);
		
		pexprLeft = CUtils::PexprLogicalJoin<CLogicalInnerJoin>(pmp, pexprLeft, pexprRight, pexprPred);
	}
	
	return pexprLeft;	
}
コード例 #2
0
//---------------------------------------------------------------------------
//	@function:
//		CXformLeftSemiJoin2InnerJoin::Transform
//
//	@doc:
//		actual transformation
//
//---------------------------------------------------------------------------
void
CXformLeftSemiJoin2InnerJoin::Transform
	(
	CXformContext *pxfctxt,
	CXformResult *pxfres,
	CExpression *pexpr
	)
	const
{
	GPOS_ASSERT(NULL != pxfctxt);
	GPOS_ASSERT(FPromising(pxfctxt->Pmp(), this, pexpr));
	GPOS_ASSERT(FCheckPattern(pexpr));

	IMemoryPool *mp = pxfctxt->Pmp();

	// extract components
	CExpression *pexprOuter = (*pexpr)[0];
	CExpression *pexprInner = (*pexpr)[1];
	CExpression *pexprScalar = (*pexpr)[2];

	pexprOuter->AddRef();
	pexprInner->AddRef();
	pexprScalar->AddRef();

	// construct grouping columns by collecting used columns in the join predicate
	// that come from join's inner child
	CColRefSet *pcrsOuterOutput = CDrvdPropRelational::GetRelationalProperties(pexprOuter->PdpDerive())->PcrsOutput();
	CColRefSet *pcrsUsed = CDrvdPropScalar::GetDrvdScalarProps(pexprScalar->PdpDerive())->PcrsUsed();
	CColRefSet *pcrsGb = GPOS_NEW(mp) CColRefSet(mp);
	pcrsGb->Include(pcrsUsed);
	pcrsGb->Difference(pcrsOuterOutput);
	GPOS_ASSERT(0 < pcrsGb->Size());

	CKeyCollection *pkc = CDrvdPropRelational::GetRelationalProperties(pexprInner->PdpDerive())->Pkc();
	if (NULL == pkc ||
		(NULL != pkc && !pkc->FKey(pcrsGb, false /*fExactMatch*/)))
	{
		// grouping columns do not cover a key on the inner side,
		// we need to create a group by on inner side
		CColRefArray *colref_array = pcrsGb->Pdrgpcr(mp);
		CExpression *pexprGb =
			GPOS_NEW(mp) CExpression
				(
				mp,
				GPOS_NEW(mp) CLogicalGbAgg(mp, colref_array, COperator::EgbaggtypeGlobal /*egbaggtype*/),
				pexprInner,
				GPOS_NEW(mp) CExpression(mp, GPOS_NEW(mp) CScalarProjectList(mp))
				);
		pexprInner = pexprGb;
	}

	CExpression *pexprInnerJoin =
		CUtils::PexprLogicalJoin<CLogicalInnerJoin>(mp, pexprOuter, pexprInner, pexprScalar);

	pcrsGb->Release();
	pxfres->Add(pexprInnerJoin);
}
コード例 #3
0
ファイル: CDecorrelator.cpp プロジェクト: HanumathRao/gporca
//---------------------------------------------------------------------------
//	@function:
//		CDecorrelator::FProcessGbAgg
//
//	@doc:
//		Decorrelate GbAgg operator
//
//---------------------------------------------------------------------------
BOOL
CDecorrelator::FProcessGbAgg
	(
	IMemoryPool *pmp,
	CExpression *pexpr,
	BOOL, // fEqualityOnly
	CExpression **ppexprDecorrelated,
	DrgPexpr *pdrgpexprCorrelations
	)
{
	CLogicalGbAgg *popAggOriginal = CLogicalGbAgg::PopConvert(pexpr->Pop());
	
	// fail if agg has outer references
	if (CUtils::FHasOuterRefs(pexpr) && !CUtils::FHasOuterRefs((*pexpr)[0]))
	{
		return false;
	}

	// TODO: 12/20/2012 - ; check for strictness of agg function

	// decorrelate relational child
	CExpression *pexprRelational = NULL;
	if (!FProcess(pmp, (*pexpr)[0], true /*fEqualityOnly*/, &pexprRelational, pdrgpexprCorrelations))
	{
		GPOS_ASSERT(NULL == pexprRelational);
		return false;
	}
	
	// get the output columns of decorrelated child
	CColRefSet *pcrsOutput = CDrvdPropRelational::Pdprel(pexprRelational->PdpDerive())->PcrsOutput();

	// create temp expression of correlations to determine inner columns
	pdrgpexprCorrelations->AddRef();
	CExpression *pexprTemp = CPredicateUtils::PexprConjunction(pmp, pdrgpexprCorrelations);
	CColRefSet *pcrs = 
		GPOS_NEW(pmp) CColRefSet(pmp,
			*(CDrvdPropScalar::Pdpscalar(pexprTemp->PdpDerive())->PcrsUsed()));
		
	pcrs->Intersection(pcrsOutput);
	pexprTemp->Release();

	// add grouping columns from original agg
	pcrs->Include(popAggOriginal->Pdrgpcr());

	// assemble grouping columns
	DrgPcr *pdrgpcr = pcrs->Pdrgpcr(pmp);
	pcrs->Release();
	
	// assemble agg
	CExpression *pexprProjList = (*pexpr)[1];
	pexprProjList->AddRef();
	CLogicalGbAgg *popAgg = GPOS_NEW(pmp) CLogicalGbAgg(pmp, pdrgpcr, popAggOriginal->Egbaggtype());
	*ppexprDecorrelated = GPOS_NEW(pmp) CExpression(pmp, popAgg, pexprRelational, pexprProjList);
	
	return true;
}
コード例 #4
0
ファイル: COptimizer.cpp プロジェクト: d/gporca
//---------------------------------------------------------------------------
//	@function:
//		COptimizer::PrintQuery
//
//	@doc:
//		Helper function to print query expression
//
//---------------------------------------------------------------------------
void
COptimizer::PrintQuery
	(
	IMemoryPool *pmp,
	CExpression *pexprTranslated,
	CQueryContext *pqc
	)
{
	CAutoTrace at(pmp);
	at.Os() << std::endl << "Algebrized query: " << std::endl << *pexprTranslated;

	DrgPexpr *pdrgpexpr = COptCtxt::PoctxtFromTLS()->Pcteinfo()->PdrgPexpr(pmp);
	const ULONG ulCTEs = pdrgpexpr->UlLength();
	if (0 < ulCTEs)
	{
		at.Os() << std::endl << "Common Table Expressions: ";
		for (ULONG ul = 0; ul < ulCTEs; ul++)
		{
			at.Os() << std::endl << *(*pdrgpexpr)[ul];
		}
	}
	pdrgpexpr->Release();

	CExpression *pexprPreprocessed = pqc->Pexpr();
	(void) pexprPreprocessed->PdpDerive();
	at.Os() << std::endl << "Algebrized preprocessed query: " << std::endl << *pexprPreprocessed;
}
コード例 #5
0
ファイル: CDecorrelator.cpp プロジェクト: HanumathRao/gporca
//---------------------------------------------------------------------------
//	@function:
//		CDecorrelator::FProcessProject
//
//	@doc:
//		Decorrelate project/sequence project
//
//---------------------------------------------------------------------------
BOOL
CDecorrelator::FProcessProject
	(
	IMemoryPool *pmp,
	CExpression *pexpr,
	BOOL fEqualityOnly,
	CExpression **ppexprDecorrelated,
	DrgPexpr *pdrgpexprCorrelations
	)
{
	COperator::EOperatorId eopid = pexpr->Pop()->Eopid();

	GPOS_ASSERT(COperator::EopLogicalProject == eopid ||
			COperator::EopLogicalSequenceProject == eopid);

	CExpression *pexprPrjList = (*pexpr)[1];

	// fail if project elements have outer references
	CColRefSet *pcrsOutput = CDrvdPropRelational::Pdprel((*pexpr)[0]->PdpDerive())->PcrsOutput();
	CColRefSet *pcrsUsed = CDrvdPropScalar::Pdpscalar(pexprPrjList->PdpDerive())->PcrsUsed();
	if (!pcrsOutput->FSubset(pcrsUsed))
	{
		return false;
	}

	if (COperator::EopLogicalSequenceProject == eopid)
	{
		(void) pexpr->PdpDerive();
		CExpressionHandle exprhdl(pmp);
		exprhdl.Attach(pexpr);
		exprhdl.DeriveProps(NULL /*pdpctxt*/);
		if (CLogicalSequenceProject::PopConvert(pexpr->Pop())->FHasLocalOuterRefs(exprhdl))
		{
			// fail if a SequenceProject has local outer references
			return false;
		}
	}

	// decorrelate relational child
	CExpression *pexprRelational = NULL;
	if (!FProcess(pmp, (*pexpr)[0], fEqualityOnly, &pexprRelational, pdrgpexprCorrelations))
	{
		GPOS_ASSERT(NULL == pexprRelational);
		return false;
	}
	
	// assemble new project
	COperator *pop = pexpr->Pop();
	pop->AddRef();
	pexprPrjList->AddRef();
	
	*ppexprDecorrelated = GPOS_NEW(pmp) CExpression(pmp, pop, pexprRelational, pexprPrjList);
	
	return true;
}
コード例 #6
0
ファイル: CXformSimplifyGbAgg.cpp プロジェクト: d/gporca
//---------------------------------------------------------------------------
//	@function:
//		CXformSimplifyGbAgg::FDropGbAgg
//
//	@doc:
//		Return true if GbAgg operator can be dropped because grouping
//		columns include a key
//
//---------------------------------------------------------------------------
BOOL
CXformSimplifyGbAgg::FDropGbAgg
	(
	IMemoryPool *pmp,
	CExpression *pexpr,
	CXformResult *pxfres
	)
{
	CLogicalGbAgg *popAgg = CLogicalGbAgg::PopConvert(pexpr->Pop());
	CExpression *pexprRelational = (*pexpr)[0];
	CExpression *pexprProjectList = (*pexpr)[1];

	if (0 < pexprProjectList->UlArity())
	{
		// GbAgg cannot be dropped if Agg functions are computed
		return false;
	}

	CKeyCollection *pkc = CDrvdPropRelational::Pdprel(pexprRelational->PdpDerive())->Pkc();
	if (NULL == pkc)
	{
		// relational child does not have key
		return false;
	}

	const ULONG ulKeys = pkc->UlKeys();
	BOOL fDrop = false;
	for (ULONG ul = 0; !fDrop && ul < ulKeys; ul++)
	{
		DrgPcr *pdrgpcrKey = pkc->PdrgpcrKey(pmp, ul);
		CColRefSet *pcrs = GPOS_NEW(pmp) CColRefSet(pmp, pdrgpcrKey);
		pdrgpcrKey->Release();

		CColRefSet *pcrsGrpCols = GPOS_NEW(pmp) CColRefSet(pmp);
		pcrsGrpCols->Include(popAgg->Pdrgpcr());
		BOOL fGrpColsHasKey = pcrsGrpCols->FSubset(pcrs);

		pcrs->Release();
		pcrsGrpCols->Release();
		if (fGrpColsHasKey)
		{
			// Gb operator can be dropped
			pexprRelational->AddRef();
			CExpression *pexprResult =
				CUtils::PexprLogicalSelect(pmp, pexprRelational, CPredicateUtils::PexprConjunction(pmp, NULL));
			pxfres->Add(pexprResult);
			fDrop = true;
		}
	}

	return fDrop;
}
コード例 #7
0
ファイル: CNormalizer.cpp プロジェクト: godouxm/gporca
//---------------------------------------------------------------------------
//	@function:
//		CNormalizer::FSimplifySelectOnOuterJoin
//
//	@doc:
//		A SELECT on top of LOJ, where SELECT's predicate is NULL-filtering and
//		uses columns from LOJ's inner child, is simplified as Inner-Join
//
//		Example:
//
//			select * from (select * from R left join S on r1=s1) as foo where foo.s1>0;
//
//			is converted to:
//
//			select * from R inner join S on r1=s1 and s1>0;
//
//
//
//---------------------------------------------------------------------------
BOOL
CNormalizer::FSimplifySelectOnOuterJoin
	(
	IMemoryPool *pmp,
	CExpression *pexprOuterJoin,
	CExpression *pexprPred, // selection predicate
	CExpression **ppexprResult
	)
{
	GPOS_ASSERT(NULL != pmp);
	GPOS_ASSERT(COperator::EopLogicalLeftOuterJoin == pexprOuterJoin->Pop()->Eopid());
	GPOS_ASSERT(pexprPred->Pop()->FScalar());
	GPOS_ASSERT(NULL != ppexprResult);

	if (0 == pexprOuterJoin->UlArity())
	{
		// exit early for leaf patterns extracted from memo
		*ppexprResult = NULL;
		return false;
	}

	CExpression *pexprOuterJoinOuterChild = (*pexprOuterJoin)[0];
	CExpression *pexprOuterJoinInnerChild = (*pexprOuterJoin)[1];
	CExpression *pexprOuterJoinPred = (*pexprOuterJoin)[2];

	CColRefSet *pcrsOutput = CDrvdPropRelational::Pdprel(pexprOuterJoinInnerChild->PdpDerive())->PcrsOutput();
	if (!GPOS_FTRACE(EopttraceDisableOuterJoin2InnerJoinRewrite) &&
		CPredicateUtils::FNullRejecting(pmp, pexprPred, pcrsOutput))
	{
		// we have a predicate on top of LOJ that uses LOJ's inner child,
		// if the predicate filters-out nulls, we can add it to the join
		// predicate and turn LOJ into Inner-Join
		pexprOuterJoinOuterChild->AddRef();
		pexprOuterJoinInnerChild->AddRef();

		*ppexprResult = GPOS_NEW(pmp) CExpression
					(
					pmp,
					GPOS_NEW(pmp) CLogicalInnerJoin(pmp),
					pexprOuterJoinOuterChild,
					pexprOuterJoinInnerChild,
					CPredicateUtils::PexprConjunction(pmp, pexprPred, pexprOuterJoinPred)
					);

		return true;
	}

	// failed to convert LOJ to inner-join
	return false;
}
コード例 #8
0
//---------------------------------------------------------------------------
//	@function:
//		CXformGbAggWithMDQA2Join::PexprMDQAs2Join
//
//	@doc:
//		Converts GbAgg with multiple distinct aggregates into a join of single
//		distinct aggregates,
//
//		distinct aggregates that share the same argument are grouped together
//		in one leaf of the generated join expression,
//
//		non-distinct aggregates are also grouped together in one leaf of the
//		generated join expression
//
//---------------------------------------------------------------------------
CExpression *
CXformGbAggWithMDQA2Join::PexprMDQAs2Join
	(
	IMemoryPool *pmp,
	CExpression *pexpr
	)
{
	GPOS_ASSERT(NULL != pexpr);
	GPOS_ASSERT(COperator::EopLogicalGbAgg == pexpr->Pop()->Eopid());
	GPOS_ASSERT(CDrvdPropScalar::Pdpscalar((*pexpr)[1]->PdpDerive())->FHasMultipleDistinctAggs());

	// extract components
	CExpression *pexprChild = (*pexpr)[0];

	CColRefSet *pcrsChildOutput = CDrvdPropRelational::Pdprel(pexprChild->PdpDerive())->PcrsOutput();
	DrgPcr *pdrgpcrChildOutput = pcrsChildOutput->Pdrgpcr(pmp);

	// create a CTE producer based on child expression
	CCTEInfo *pcteinfo = COptCtxt::PoctxtFromTLS()->Pcteinfo();
	const ULONG ulCTEId = pcteinfo->UlNextId();
	(void) CXformUtils::PexprAddCTEProducer(pmp, ulCTEId, pdrgpcrChildOutput, pexprChild);

	// create a CTE consumer with child output columns
	CExpression *pexprConsumer =
			GPOS_NEW(pmp) CExpression
				(
				pmp,
				GPOS_NEW(pmp) CLogicalCTEConsumer(pmp, ulCTEId, pdrgpcrChildOutput)
				);
	pcteinfo->IncrementConsumers(ulCTEId);

	// finalize GbAgg expression by replacing its child with CTE consumer
	pexpr->Pop()->AddRef();
	(*pexpr)[1]->AddRef();
	CExpression *pexprGbAggWithConsumer = GPOS_NEW(pmp) CExpression(pmp, pexpr->Pop(), pexprConsumer, (*pexpr)[1]);

	CExpression *pexprJoinDQAs = CXformUtils::PexprGbAggOnCTEConsumer2Join(pmp, pexprGbAggWithConsumer);
	GPOS_ASSERT(NULL != pexprJoinDQAs);

	pexprGbAggWithConsumer->Release();

	return GPOS_NEW(pmp) CExpression
					(
					pmp,
					GPOS_NEW(pmp) CLogicalCTEAnchor(pmp, ulCTEId),
					pexprJoinDQAs
					);
}
コード例 #9
0
ファイル: CStatsPredUtils.cpp プロジェクト: d/gporca
//---------------------------------------------------------------------------
//	@function:
//		CStatsPredUtils::PstatspredConj
//
//	@doc:
//		Create conjunctive statistics filter composed of the extracted
//		components of the conjunction
//---------------------------------------------------------------------------
CStatsPred *
CStatsPredUtils::PstatspredConj
	(
	IMemoryPool *pmp,
	CExpression *pexprScalar,
	CColRefSet *pcrsOuterRefs
	)
{
	GPOS_ASSERT(NULL != pexprScalar);
	DrgPexpr *pdrgpexprConjuncts = CPredicateUtils::PdrgpexprConjuncts(pmp, pexprScalar);
	const ULONG ulLen = pdrgpexprConjuncts->UlLength();

	DrgPstatspred *pdrgpstatspred = GPOS_NEW(pmp) DrgPstatspred(pmp);
	for (ULONG ul = 0; ul < ulLen; ul++)
	{
		CExpression *pexprPred = (*pdrgpexprConjuncts)[ul];
		CColRefSet *pcrsUsed = CDrvdPropScalar::Pdpscalar(pexprPred->PdpDerive())->PcrsUsed();
		if (NULL != pcrsOuterRefs && pcrsOuterRefs->FSubset(pcrsUsed))
		{
			// skip predicate with outer references
			continue;
		}

		if (CPredicateUtils::FOr(pexprPred))
		{
			CStatsPred *pstatspredDisj = PstatspredDisj(pmp, pexprPred, pcrsOuterRefs);
			if (NULL != pstatspredDisj)
			{
				pdrgpstatspred->Append(pstatspredDisj);
			}
		}
		else
		{
			AddSupportedStatsFilters(pmp, pdrgpstatspred, pexprPred, pcrsOuterRefs);
		}
	}

	pdrgpexprConjuncts->Release();

	if (0 < pdrgpstatspred->UlLength())
	{
		return GPOS_NEW(pmp) CStatsPredConj(pdrgpstatspred);
	}

	pdrgpstatspred->Release();

	return NULL;
}
コード例 #10
0
//---------------------------------------------------------------------------
//	@function:
//		CLogicalCTEAnchor::PpartinfoDerive
//
//	@doc:
//		Derive part consumer
//
//---------------------------------------------------------------------------
CPartInfo *
CLogicalCTEAnchor::PpartinfoDerive
	(
	IMemoryPool *pmp,
	CExpressionHandle &exprhdl
	)
	const
{
	CPartInfo *ppartinfoChild = exprhdl.Pdprel(0 /*ulChildIndex*/)->Ppartinfo();
	GPOS_ASSERT(NULL != ppartinfoChild);

	CExpression *pexprProducer = COptCtxt::PoctxtFromTLS()->Pcteinfo()->PexprCTEProducer(m_ulId);
	GPOS_ASSERT(NULL != pexprProducer);
	CPartInfo *ppartinfoCTEProducer = CDrvdPropRelational::Pdprel(pexprProducer->PdpDerive())->Ppartinfo();

	return CPartInfo::PpartinfoCombine(pmp, ppartinfoChild, ppartinfoCTEProducer);
}
コード例 #11
0
ファイル: CStatsPredUtils.cpp プロジェクト: d/gporca
//---------------------------------------------------------------------------
//	@function:
//		CStatsPredUtils::PstatspredDisj
//
//	@doc:
//		Create disjunctive statistics filter composed of the extracted
//		components of the disjunction
//---------------------------------------------------------------------------
CStatsPred *
CStatsPredUtils::PstatspredDisj
	(
	IMemoryPool *pmp,
	CExpression *pexprPred,
	CColRefSet *pcrsOuterRefs
	)
{
	GPOS_ASSERT(NULL != pexprPred);
	GPOS_ASSERT(CPredicateUtils::FOr(pexprPred));

	DrgPstatspred *pdrgpstatspredDisjChild = GPOS_NEW(pmp) DrgPstatspred(pmp);

	// remove duplicate components of the OR tree
	CExpression *pexprNew = CExpressionUtils::PexprDedupChildren(pmp, pexprPred);

	// extract the components of the OR tree
	DrgPexpr *pdrgpexpr = CPredicateUtils::PdrgpexprDisjuncts(pmp, pexprNew);
	const ULONG ulLen = pdrgpexpr->UlLength();
	for (ULONG ul = 0; ul < ulLen; ul++)
	{
		CExpression *pexpr = (*pdrgpexpr)[ul];
		CColRefSet *pcrsUsed = CDrvdPropScalar::Pdpscalar(pexpr->PdpDerive())->PcrsUsed();
		if (NULL != pcrsOuterRefs && pcrsOuterRefs->FSubset(pcrsUsed))
		{
			// skip predicate with outer references
			continue;
		}

		AddSupportedStatsFilters(pmp, pdrgpstatspredDisjChild, pexpr, pcrsOuterRefs);
	}

	// clean up
	pexprNew->Release();
	pdrgpexpr->Release();

	if (0 < pdrgpstatspredDisjChild->UlLength())
	{
		return GPOS_NEW(pmp) CStatsPredDisj(pdrgpstatspredDisjChild);
	}

	pdrgpstatspredDisjChild->Release();

	return NULL;
}
コード例 #12
0
//---------------------------------------------------------------------------
//	@function:
//		CExpressionHandle::DeriveProps
//
//	@doc:
//		Recursive property derivation
//
//---------------------------------------------------------------------------
void
CExpressionHandle::DeriveProps
	(
	CDrvdPropCtxt *pdpctxt
	)
{
	GPOS_ASSERT(NULL == m_pdrgpdp);
	GPOS_ASSERT(NULL == m_pdp);
	GPOS_CHECK_ABORT;

	if (NULL != m_pgexpr)
	{
		CopyGroupProps();
		return;
	}
	GPOS_ASSERT(NULL != m_pexpr);

	// check if expression already has derived props
	if (NULL != m_pexpr->Pdp(m_pexpr->Ept()))
	{
		CopyExprProps();
		return;
	}

	// copy stats of attached expression
	CopyStats();

	// extract children's properties
	m_pdrgpdp = GPOS_NEW(m_pmp) DrgPdp(m_pmp);
	const ULONG ulArity = m_pexpr->UlArity();
	for (ULONG ul = 0; ul < ulArity; ul++)
	{
		CExpression *pexprChild = (*m_pexpr)[ul];
		CDrvdProp *pdp = pexprChild->PdpDerive(pdpctxt);
		pdp->AddRef();
		m_pdrgpdp->Append(pdp);

		// add child props to derivation context
		CDrvdPropCtxt::AddDerivedProps(pdp, pdpctxt);
	}

	// create/derive local properties
	m_pdp = Pop()->PdpCreate(m_pmp);
	m_pdp->Derive(m_pmp, *this, pdpctxt);
}
コード例 #13
0
//---------------------------------------------------------------------------
//	@function:
//		CXformSimplifyLeftOuterJoin::Transform
//
//	@doc:
//		Actual transformation to simplify left outer join
//
//---------------------------------------------------------------------------
void
CXformSimplifyLeftOuterJoin::Transform
	(
	CXformContext *pxfctxt,
	CXformResult *pxfres,
	CExpression *pexpr
	)
	const
{
	GPOS_ASSERT(NULL != pxfctxt);
	GPOS_ASSERT(NULL != pxfres);
	GPOS_ASSERT(FPromising(pxfctxt->Pmp(), this, pexpr));
	GPOS_ASSERT(FCheckPattern(pexpr));

	IMemoryPool *pmp = pxfctxt->Pmp();

	// extract components
	CExpression *pexprOuter = (*pexpr)[0];
	CExpression *pexprInner = (*pexpr)[1];
	CExpression *pexprScalar = (*pexpr)[2];

	pexprOuter->AddRef();
	pexprScalar->AddRef();
	CExpression *pexprResult = NULL;

	// inner child of LOJ can be replaced with empty table
	GPOS_ASSERT(CUtils::FScalarConstFalse(pexprScalar));

	// extract output columns of inner child
	DrgPcr *pdrgpcr = CDrvdPropRelational::Pdprel(pexprInner->PdpDerive())->PcrsOutput()->Pdrgpcr(pmp);

	// generate empty constant table with the same columns
	COperator *popCTG = GPOS_NEW(pmp) CLogicalConstTableGet(pmp, pdrgpcr, GPOS_NEW(pmp) DrgPdrgPdatum(pmp));
	pexprResult =
		GPOS_NEW(pmp) CExpression
			(
			pmp,
			GPOS_NEW(pmp) CLogicalLeftOuterJoin(pmp),
			pexprOuter,
			GPOS_NEW(pmp) CExpression(pmp, popCTG),
			pexprScalar
			);

	pxfres->Add(pexprResult);
}
コード例 #14
0
//---------------------------------------------------------------------------
//	@function:
//		CPartitionPropagationSpec::PdrgpexprPredicatesOnKey
//
//	@doc:
//		Returns an array of predicates on the given partitioning key given
//		an array of predicates on all keys
//
//---------------------------------------------------------------------------
DrgPexpr *
CPartitionPropagationSpec::PdrgpexprPredicatesOnKey
	(
	IMemoryPool *pmp,
	DrgPexpr *pdrgpexpr,
	CColRef *pcr,
	CColRefSet *pcrsKeys,
	CBitSet **ppbs
	)
{
	GPOS_ASSERT(NULL != pdrgpexpr);
	GPOS_ASSERT(NULL != pcr);
	GPOS_ASSERT(NULL != ppbs);
	GPOS_ASSERT(NULL != *ppbs);

	DrgPexpr *pdrgpexprResult = GPOS_NEW(pmp) DrgPexpr(pmp);

	const ULONG ulLen = pdrgpexpr->UlLength();
	for (ULONG ul = 0; ul < ulLen; ul++)
	{
		if ((*ppbs)->FBit(ul))
		{
			// this expression has already been added for another column
			continue;
		}

		CExpression *pexpr = (*pdrgpexpr)[ul];
		GPOS_ASSERT(pexpr->Pop()->FScalar());

		CColRefSet *pcrsUsed = CDrvdPropScalar::Pdpscalar(pexpr->PdpDerive())->PcrsUsed();
		CColRefSet *pcrsUsedKeys = GPOS_NEW(pmp) CColRefSet(pmp, *pcrsUsed);
		pcrsUsedKeys->Intersection(pcrsKeys);

		if (1 == pcrsUsedKeys->CElements() && pcrsUsedKeys->FMember(pcr))
		{
			pexpr->AddRef();
			pdrgpexprResult->Append(pexpr);
			(*ppbs)->FExchangeSet(ul);
		}

		pcrsUsedKeys->Release();
	}

	return pdrgpexprResult;
}
コード例 #15
0
//---------------------------------------------------------------------------
//	@function:
//		CPartitionPropagationSpec::PdrgpexprPredicatesOnKey
//
//	@doc:
//		Returns an array of predicates on the given partitioning key given
//		an array of predicates on all keys
//
//---------------------------------------------------------------------------
CExpressionArray *
CPartitionPropagationSpec::PdrgpexprPredicatesOnKey
	(
	IMemoryPool *mp,
	CExpressionArray *pdrgpexpr,
	CColRef *colref,
	CColRefSet *pcrsKeys,
	CBitSet **ppbs
	)
{
	GPOS_ASSERT(NULL != pdrgpexpr);
	GPOS_ASSERT(NULL != colref);
	GPOS_ASSERT(NULL != ppbs);
	GPOS_ASSERT(NULL != *ppbs);

	CExpressionArray *pdrgpexprResult = GPOS_NEW(mp) CExpressionArray(mp);

	const ULONG length = pdrgpexpr->Size();
	for (ULONG ul = 0; ul < length; ul++)
	{
		if ((*ppbs)->Get(ul))
		{
			// this expression has already been added for another column
			continue;
		}

		CExpression *pexpr = (*pdrgpexpr)[ul];
		GPOS_ASSERT(pexpr->Pop()->FScalar());

		CColRefSet *pcrsUsed = CDrvdPropScalar::GetDrvdScalarProps(pexpr->PdpDerive())->PcrsUsed();
		CColRefSet *pcrsUsedKeys = GPOS_NEW(mp) CColRefSet(mp, *pcrsUsed);
		pcrsUsedKeys->Intersection(pcrsKeys);

		if (1 == pcrsUsedKeys->Size() && pcrsUsedKeys->FMember(colref))
		{
			pexpr->AddRef();
			pdrgpexprResult->Append(pexpr);
			(*ppbs)->ExchangeSet(ul);
		}

		pcrsUsedKeys->Release();
	}

	return pdrgpexprResult;
}
コード例 #16
0
ファイル: CDecorrelator.cpp プロジェクト: HanumathRao/gporca
//---------------------------------------------------------------------------
//	@function:
//		CDecorrelator::FProcessAssert
//
//	@doc:
//		Decorrelate assert operator
//
//---------------------------------------------------------------------------
BOOL
CDecorrelator::FProcessAssert
	(
	IMemoryPool *pmp,
	CExpression *pexpr,
	BOOL fEqualityOnly,
	CExpression **ppexprDecorrelated,
	DrgPexpr *pdrgpexprCorrelations
	)
{
	GPOS_ASSERT(NULL != pexpr);

	COperator *pop = pexpr->Pop();
	GPOS_ASSERT(COperator::EopLogicalAssert == pop->Eopid());

	CExpression *pexprScalar = (*pexpr)[1];

	// fail if assert expression has outer references
	CColRefSet *pcrsOutput = CDrvdPropRelational::Pdprel((*pexpr)[0]->PdpDerive())->PcrsOutput();
	CColRefSet *pcrsUsed = CDrvdPropScalar::Pdpscalar(pexprScalar->PdpDerive())->PcrsUsed();
	if (!pcrsOutput->FSubset(pcrsUsed))
	{
		return false;
	}

	// decorrelate relational child
	CExpression *pexprRelational = NULL;
	if (!FProcess(pmp, (*pexpr)[0], fEqualityOnly, &pexprRelational, pdrgpexprCorrelations))
	{
		GPOS_ASSERT(NULL == pexprRelational);
		return false;
	}

	// assemble new project
	pop->AddRef();
	pexprScalar->AddRef();
	*ppexprDecorrelated = GPOS_NEW(pmp) CExpression(pmp, pop, pexprRelational, pexprScalar);

	return true;
}
コード例 #17
0
//---------------------------------------------------------------------------
//	@function:
//		CPredicateUtilsTest::EresUnittest_Disjunctions
//
//	@doc:
//		Test extraction and construction of disjuncts
//
//---------------------------------------------------------------------------
GPOS_RESULT
CPredicateUtilsTest::EresUnittest_Disjunctions()
{
	CAutoMemoryPool amp;
	IMemoryPool *mp = amp.Pmp();

	// setup a file-based provider
	CMDProviderMemory *pmdp = CTestUtils::m_pmdpf;
	pmdp->AddRef();
	CMDAccessor mda(mp, CMDCache::Pcache(), CTestUtils::m_sysidDefault, pmdp);

	// install opt context in TLS
	CAutoOptCtxt aoc
					(
					mp,
					&mda,
					NULL,  /* pceeval */
					CTestUtils::GetCostModel(mp)
					);

	// build disjunction
	CExpressionArray *pdrgpexpr = GPOS_NEW(mp) CExpressionArray(mp);
	const ULONG ulDisjs = 3;
	for (ULONG ul = 0; ul < ulDisjs; ul++)
	{
		pdrgpexpr->Append(CUtils::PexprScalarConstBool(mp, false /*fValue*/));
	}
	CExpression *pexprDisjunction = CUtils::PexprScalarBoolOp(mp, CScalarBoolOp::EboolopOr, pdrgpexpr);

	// break into disjuncts
	CExpressionArray *pdrgpexprExtract = CPredicateUtils::PdrgpexprDisjuncts(mp, pexprDisjunction);
	GPOS_ASSERT(pdrgpexprExtract->Size() == ulDisjs);

	// collapse into single disjunct
	CExpression *pexpr = CPredicateUtils::PexprDisjunction(mp, pdrgpexprExtract);
	GPOS_ASSERT(NULL != pexpr);
	GPOS_ASSERT(CUtils::FScalarConstFalse(pexpr));
	pexpr->Release();

	// collapse empty input array to disjunct
	CExpression *pexprSingleton = CPredicateUtils::PexprDisjunction(mp, NULL /*pdrgpexpr*/);
	GPOS_ASSERT(NULL != pexprSingleton);
	pexprSingleton->Release();

	pexprDisjunction->Release();

	// disjunction on scalar comparisons
	CExpression *pexprGet = CTestUtils::PexprLogicalGet(mp);
	CColRefSet *pcrs = CDrvdPropRelational::GetRelationalProperties(pexprGet->PdpDerive())->PcrsOutput();
	CColRefSetIter crsi(*pcrs);

#ifdef GPOS_DEBUG
	BOOL fAdvance =
#endif
	crsi.Advance();
	GPOS_ASSERT(fAdvance);
	CColRef *pcr1 = crsi.Pcr();

#ifdef GPOS_DEBUG
	fAdvance =
#endif
	crsi.Advance();
	GPOS_ASSERT(fAdvance);
	CColRef *pcr2 = crsi.Pcr();

#ifdef GPOS_DEBUG
	fAdvance =
#endif
	crsi.Advance();
	GPOS_ASSERT(fAdvance);
	CColRef *pcr3 = crsi.Pcr();

	CExpression *pexprCmp1 = CUtils::PexprScalarCmp(mp, pcr1, pcr2, IMDType::EcmptEq);
	CExpression *pexprCmp2 = CUtils::PexprScalarCmp(mp, pcr1, CUtils::PexprScalarConstInt4(mp, 1 /*val*/), IMDType::EcmptEq);

	{
		CExpression *pexprDisj = CPredicateUtils::PexprDisjunction(mp, pexprCmp1, pexprCmp2);
		pdrgpexprExtract = CPredicateUtils::PdrgpexprDisjuncts(mp, pexprDisj);
		GPOS_ASSERT(2 == pdrgpexprExtract->Size());
		pdrgpexprExtract->Release();
		pexprDisj->Release();
	}


	{
		CExpressionArray *pdrgpexpr = GPOS_NEW(mp) CExpressionArray(mp);
		CExpression *pexprCmp3 = CUtils::PexprScalarCmp(mp, pcr2, pcr1, IMDType::EcmptG);
		CExpression *pexprCmp4 = CUtils::PexprScalarCmp(mp, CUtils::PexprScalarConstInt4(mp, 200 /*val*/), pcr3, IMDType::EcmptL);
		pexprCmp1->AddRef();
		pexprCmp2->AddRef();

		pdrgpexpr->Append(pexprCmp3);
		pdrgpexpr->Append(pexprCmp4);
		pdrgpexpr->Append(pexprCmp1);
		pdrgpexpr->Append(pexprCmp2);

		CExpression *pexprDisj = CPredicateUtils::PexprDisjunction(mp, pdrgpexpr);
		pdrgpexprExtract = CPredicateUtils::PdrgpexprDisjuncts(mp, pexprDisj);
		GPOS_ASSERT(4 == pdrgpexprExtract->Size());
		pdrgpexprExtract->Release();
		pexprDisj->Release();
	}

	pexprCmp1->Release();
	pexprCmp2->Release();
	pexprGet->Release();

	return GPOS_OK;
}
コード例 #18
0
//---------------------------------------------------------------------------
//	@function:
//		CPartitionPropagationSpec::AppendEnforcers
//
//	@doc:
//		Add required enforcers to dynamic array
//
//---------------------------------------------------------------------------
void
CPartitionPropagationSpec::AppendEnforcers
	(
	IMemoryPool *mp,
	CExpressionHandle &exprhdl,
	CReqdPropPlan *
#ifdef GPOS_DEBUG
	prpp
#endif // GPOS_DEBUG
	,
	CExpressionArray *pdrgpexpr, 
	CExpression *pexpr
	)
{
	GPOS_ASSERT(NULL != prpp);
	GPOS_ASSERT(NULL != mp);
	GPOS_ASSERT(NULL != pdrgpexpr);
	GPOS_ASSERT(NULL != pexpr);
	
	ULongPtrArray *pdrgpul = m_ppim->PdrgpulScanIds(mp);
	const ULONG size = pdrgpul->Size();
	
	for (ULONG ul = 0; ul < size; ul++)
	{
		ULONG scan_id = *((*pdrgpul)[ul]);
		GPOS_ASSERT(m_ppim->Contains(scan_id));
		
		if (CPartIndexMap::EpimConsumer != m_ppim->Epim(scan_id) || 0 < m_ppim->UlExpectedPropagators(scan_id))
		{
			continue;
		}
		
		if (!FRequiresPartitionPropagation(mp, pexpr, exprhdl, scan_id))
		{
			continue;
		}
		
		CExpression *pexprResolver = NULL;

		IMDId *mdid = m_ppim->GetRelMdId(scan_id);
		CColRef2dArray *pdrgpdrgpcrKeys = NULL;
		CPartKeysArray *pdrgppartkeys = m_ppim->Pdrgppartkeys(scan_id);
		CPartConstraint *ppartcnstr = m_ppim->PpartcnstrRel(scan_id);
		UlongToPartConstraintMap *ppartcnstrmap = m_ppim->Ppartcnstrmap(scan_id);
		mdid->AddRef();
		ppartcnstr->AddRef();
		ppartcnstrmap->AddRef();
		pexpr->AddRef();
		
		// check if there is a predicate on this part index id
		UlongToExprMap *phmulexprEqFilter = GPOS_NEW(mp) UlongToExprMap(mp);
		UlongToExprMap *phmulexprFilter = GPOS_NEW(mp) UlongToExprMap(mp);
		CExpression *pexprResidual = NULL;
		if (m_ppfm->FContainsScanId(scan_id))
		{
			CExpression *pexprScalar = PexprFilter(mp, scan_id);
			
			// find out which keys are used in the predicate, in case there are multiple
			// keys at this point (e.g. from a union of multiple CTE consumers)
			CColRefSet *pcrsUsed = CDrvdPropScalar::GetDrvdScalarProps(pexprScalar->PdpDerive())->PcrsUsed();
			const ULONG ulKeysets = pdrgppartkeys->Size();
			for (ULONG ulKey = 0; NULL == pdrgpdrgpcrKeys && ulKey < ulKeysets; ulKey++)
			{
				// get partition key
				CPartKeys *ppartkeys = (*pdrgppartkeys)[ulKey];
				if (ppartkeys->FOverlap(pcrsUsed))
				{
					pdrgpdrgpcrKeys = ppartkeys->Pdrgpdrgpcr();
				}
			}
			
                        // if we cannot find partition keys mapping the partition predicates, fall back to planner
                        if (NULL == pdrgpdrgpcrKeys)
                        {
                            GPOS_RAISE(gpopt::ExmaGPOPT, gpopt::ExmiUnsatisfiedRequiredProperties);
                        }

			pdrgpdrgpcrKeys->AddRef();

			// split predicates and put them in the appropriate hashmaps
			SplitPartPredicates(mp, pexprScalar, pdrgpdrgpcrKeys, phmulexprEqFilter, phmulexprFilter, &pexprResidual);
			pexprScalar->Release();
		}
		else
		{
			// doesn't matter which keys we use here since there is no filter
			GPOS_ASSERT(1 <= pdrgppartkeys->Size());
			pdrgpdrgpcrKeys = (*pdrgppartkeys)[0]->Pdrgpdrgpcr();
			pdrgpdrgpcrKeys->AddRef();
		}

		pexprResolver = GPOS_NEW(mp) CExpression
									(
									mp,
									GPOS_NEW(mp) CPhysicalPartitionSelector
												(
												mp,
												scan_id,
												mdid,
												pdrgpdrgpcrKeys,
												ppartcnstrmap,
												ppartcnstr,
												phmulexprEqFilter,
												phmulexprFilter,
												pexprResidual
												),
									pexpr
									);
		
		pdrgpexpr->Append(pexprResolver);
	}
	pdrgpul->Release();
}
コード例 #19
0
//---------------------------------------------------------------------------
//	@function:
//		CContradictionTest::EresUnittest_Constraint
//
//	@doc:
//		Tests for constraint property derivation and constraint push down
//
//---------------------------------------------------------------------------
GPOS_RESULT
CContradictionTest::EresUnittest_Constraint()
{
	CAutoMemoryPool amp;
	IMemoryPool *pmp = amp.Pmp();

	// setup a file-based provider
	CMDProviderMemory *pmdp = CTestUtils::m_pmdpf;
	pmdp->AddRef();
	CMDAccessor mda(pmp, CMDCache::Pcache(), CTestUtils::m_sysidDefault, pmdp);


	typedef CExpression *(*Pfpexpr)(IMemoryPool*);

	Pfpexpr rgpf[] =
		{
		CTestUtils::PexprLogicalApplyWithOuterRef<CLogicalInnerApply>,
		CTestUtils::PexprLogicalApply<CLogicalLeftSemiApply>,
		CTestUtils::PexprLogicalApply<CLogicalLeftAntiSemiApply>,
		CTestUtils::PexprLogicalApplyWithOuterRef<CLogicalLeftOuterApply>,
		CTestUtils::PexprLogicalGet,
		CTestUtils::PexprLogicalGetPartitioned,
		CTestUtils::PexprLogicalSelect,
		CTestUtils::PexprLogicalSelectCmpToConst,
		CTestUtils::PexprLogicalSelectPartitioned,
		CTestUtils::PexprLogicalSelectWithContradiction,
		CTestUtils::PexprLogicalJoin<CLogicalInnerJoin>,
		CTestUtils::PexprLogicalJoin<CLogicalLeftOuterJoin>,
		CTestUtils::PexprLogicalJoin<CLogicalLeftSemiJoin>,
		CTestUtils::PexprLogicalJoin<CLogicalLeftAntiSemiJoin>,
		CTestUtils::PexprLogicalGbAgg,
		CTestUtils::PexprLogicalGbAggOverJoin,
		CTestUtils::PexprLogicalGbAggWithSum,
		CTestUtils::PexprLogicalLimit,
		CTestUtils::PexprLogicalNAryJoin,
		CTestUtils::PexprLogicalProject,
		CTestUtils::PexprConstTableGet5,
		CTestUtils::PexprLogicalDynamicGet,
		CTestUtils::PexprLogicalSequence,
		CTestUtils::PexprLogicalTVFTwoArgs,
		};

	for (ULONG i = 0; i < GPOS_ARRAY_SIZE(rgpf); i++)
	{
		// install opt context in TLS
		CAutoOptCtxt aoc
						(
						pmp,
						&mda,
						NULL,  /* pceeval */
						CTestUtils::Pcm(pmp)
						);

		// generate simple expression
		CExpression *pexpr = rgpf[i](pmp);

		// self-match
		GPOS_ASSERT(pexpr->FMatchDebug(pexpr));

		// debug print
		CWStringDynamic str(pmp, GPOS_WSZ_LIT("\n"));
		COstreamString oss(&str);

		oss << "EXPR:" << std::endl << *pexpr << std::endl;
		GPOS_TRACE(str.Wsz());
		str.Reset();


#ifdef GPOS_DEBUG
		// derive properties on expression
		(void) pexpr->PdpDerive();

		oss << std::endl << "DERIVED PROPS:" << std::endl;
		GPOS_TRACE(str.Wsz());
		str.Reset();
		pexpr->DbgPrint();
#endif // GPOS_DEBUG

 		CExpression *pexprPreprocessed = CExpressionPreprocessor::PexprPreprocess(pmp, pexpr);
		oss	<< std::endl << "PREPROCESSED EXPR:" << std::endl << *pexprPreprocessed << std::endl;
		GPOS_TRACE(str.Wsz());
		str.Reset();

		// cleanup
		pexprPreprocessed->Release();
		pexpr->Release();
	}

	return GPOS_OK;
}
コード例 #20
0
//---------------------------------------------------------------------------
//	@function:
//		CXformSelect2PartialDynamicIndexGet::Transform
//
//	@doc:
//		Actual transformation
//
//---------------------------------------------------------------------------
void
CXformSelect2PartialDynamicIndexGet::Transform
	(
	CXformContext *pxfctxt,
	CXformResult *pxfres,
	CExpression *pexpr
	)
	const
{
	GPOS_ASSERT(NULL != pxfctxt);
	GPOS_ASSERT(FPromising(pxfctxt->Pmp(), this, pexpr));
	GPOS_ASSERT(FCheckPattern(pexpr));

	IMemoryPool *pmp = pxfctxt->Pmp();

	// extract components
	CExpression *pexprRelational = (*pexpr)[0];
	CExpression *pexprScalar = (*pexpr)[1];

	// get the indexes on this relation
	CLogicalDynamicGet *popGet = CLogicalDynamicGet::PopConvert(pexprRelational->Pop());
	
	if (popGet->FPartial())
	{
		// already a partial dynamic get; do not try to split further
		return;
	}
	
	CTableDescriptor *ptabdesc = popGet->Ptabdesc();
	CMDAccessor *pmda = COptCtxt::PoctxtFromTLS()->Pmda();
	const IMDRelation *pmdrel = pmda->Pmdrel(ptabdesc->Pmdid());
	const ULONG ulIndices = pmdrel->UlIndices();

	if (0 == ulIndices)
	{
		// no indexes on the table
		return;
	}

	// array of expressions in the scalar expression
	DrgPexpr *pdrgpexpr = CPredicateUtils::PdrgpexprConjuncts(pmp, pexprScalar);
	GPOS_ASSERT(0 < pdrgpexpr->UlLength());

	// derive the scalar and relational properties to build set of required columns
	CColRefSet *pcrsOutput = CDrvdPropRelational::Pdprel(pexpr->PdpDerive())->PcrsOutput();
	CColRefSet *pcrsScalarExpr = CDrvdPropScalar::Pdpscalar(pexprScalar->PdpDerive())->PcrsUsed();

	CColRefSet *pcrsReqd = GPOS_NEW(pmp) CColRefSet(pmp);
	pcrsReqd->Include(pcrsOutput);
	pcrsReqd->Include(pcrsScalarExpr);

	CPartConstraint *ppartcnstr = popGet->Ppartcnstr();
	ppartcnstr->AddRef();

	// find a candidate set of partial index combinations
	DrgPdrgPpartdig *pdrgpdrgppartdig = CXformUtils::PdrgpdrgppartdigCandidates
										(
										pmp,
										pmda,
										pdrgpexpr,
										popGet->PdrgpdrgpcrPart(),
										pmdrel,
										ppartcnstr,
										popGet->PdrgpcrOutput(),
										pcrsReqd,
										pcrsScalarExpr,
										NULL // pcrsAcceptedOuterRefs
										);
	
	// construct alternative partial index scan plans
	const ULONG ulCandidates = pdrgpdrgppartdig->UlLength();
	for (ULONG ul = 0; ul < ulCandidates; ul++)
	{
		DrgPpartdig *pdrgppartdig = (*pdrgpdrgppartdig)[ul];
		CreatePartialIndexGetPlan(pmp, pexpr, pdrgppartdig, pmdrel, pxfres);
	}

	ppartcnstr->Release();
	pcrsReqd->Release();
	pdrgpexpr->Release();
	pdrgpdrgppartdig->Release();
}
コード例 #21
0
//---------------------------------------------------------------------------
//	@function:
//		CLogicalDynamicGetBase::PstatsDeriveFilter
//
//	@doc:
//		Derive stats from base table using filters on partition and/or index columns
//
//---------------------------------------------------------------------------
IStatistics *
CLogicalDynamicGetBase::PstatsDeriveFilter
	(
	IMemoryPool *pmp,
	CExpressionHandle &exprhdl,
	CExpression *pexprFilter
	)
	const
{
	CExpression *pexprFilterNew = NULL;
	CConstraint *pcnstr = m_ppartcnstr->PcnstrCombined();
	if (m_fPartial && NULL != pcnstr && !pcnstr->FUnbounded())
	{
		if (NULL == pexprFilter)
		{
			pexprFilterNew = pcnstr->PexprScalar(pmp);
			pexprFilterNew->AddRef();
		}
		else
		{
			pexprFilterNew = CPredicateUtils::PexprConjunction(pmp, pexprFilter, pcnstr->PexprScalar(pmp));
		}
	}
	else if (NULL != pexprFilter)
	{
		pexprFilterNew = pexprFilter;
		pexprFilterNew->AddRef();
	}

	CColRefSet *pcrsStat = GPOS_NEW(pmp) CColRefSet(pmp);
	CDrvdPropScalar *pdpscalar = NULL;

	if (NULL != pexprFilterNew)
	{
		pdpscalar = CDrvdPropScalar::Pdpscalar(pexprFilterNew->PdpDerive());
		pcrsStat->Include(pdpscalar->PcrsUsed());
	}

	// requesting statistics on distribution columns to estimate data skew
	if (NULL != m_pcrsDist)
	{
		pcrsStat->Include(m_pcrsDist);
	}


	IStatistics *pstatsFullTable = PstatsBaseTable(pmp, exprhdl, m_ptabdesc, pcrsStat);
	
	pcrsStat->Release();
	
	if (NULL == pexprFilterNew || pdpscalar->FHasSubquery())
	{
		return pstatsFullTable;
	}

	CStatsPred *pstatspred =  CStatsPredUtils::PstatspredExtract
												(
												pmp, 
												pexprFilterNew, 
												NULL /*pcrsOuterRefs*/
												);
	pexprFilterNew->Release();

	IStatistics *pstatsResult = pstatsFullTable->PstatsFilter
													(
													pmp, 
													pstatspred, 
													true /* fCapNdvs */ 
													);
	pstatspred->Release();
	pstatsFullTable->Release();

	return pstatsResult;
}
コード例 #22
0
//---------------------------------------------------------------------------
//	@function:
//		CXformSubqJoin2Apply::PexprSubqueryPushdown
//
//	@doc:
//		Push down subquery below join
//
//---------------------------------------------------------------------------
CExpression *
CXformSubqJoin2Apply::PexprSubqueryPushDown
	(
	IMemoryPool *mp,
	CExpression *pexpr,
	BOOL fEnforceCorrelatedApply
	)
{
	GPOS_ASSERT(NULL != pexpr);
	GPOS_ASSERT(COperator::EopLogicalSelect == pexpr->Pop()->Eopid());

	CExpression *pexprJoin = (*pexpr)[0];
	const ULONG arity = pexprJoin->Arity();
	CExpression *pexprScalar = (*pexpr)[1];
	CExpression *join_pred_expr = (*pexprJoin)[arity - 1];

	// collect output columns of all logical children
	CColRefSetArray *pdrgpcrs = GPOS_NEW(mp) CColRefSetArray(mp);
	CExpressionArrays *pdrgpdrgpexprSubqs = GPOS_NEW(mp) CExpressionArrays(mp);
	for (ULONG ul = 0; ul < arity - 1; ul++)
	{
		CExpression *pexprChild = (*pexprJoin)[ul];
		CColRefSet *pcrsOutput = CDrvdPropRelational::GetRelationalProperties(pexprChild->PdpDerive())->PcrsOutput();
		pcrsOutput->AddRef();
		pdrgpcrs->Append(pcrsOutput);

		pdrgpdrgpexprSubqs->Append(GPOS_NEW(mp) CExpressionArray(mp));
	}

	// collect subqueries that exclusively use columns from each join child
	CollectSubqueries(mp, pexprScalar, pdrgpcrs, pdrgpdrgpexprSubqs);

	// create new join children by pushing subqueries to Project nodes on top
	// of corresponding join children
	CExpressionArray *pdrgpexprNewChildren = GPOS_NEW(mp) CExpressionArray(mp);
	ExprToColRefMap *phmexprcr = GPOS_NEW(mp) ExprToColRefMap(mp);
	for (ULONG ulChild = 0; ulChild < arity - 1; ulChild++)
	{
		CExpression *pexprChild = (*pexprJoin)[ulChild];
		pexprChild->AddRef();
		CExpression *pexprNewChild = pexprChild;

		CExpressionArray *pdrgpexprSubqs = (*pdrgpdrgpexprSubqs)[ulChild];
		const ULONG ulSubqs = pdrgpexprSubqs->Size();
		if (0 < ulSubqs)
		{
			// join child has pushable subqueries
			pexprNewChild = CUtils::PexprAddProjection(mp, pexprChild, pdrgpexprSubqs);
			CExpression *pexprPrjList = (*pexprNewChild)[1];

			// add pushed subqueries to map
			for (ULONG ulSubq = 0; ulSubq < ulSubqs; ulSubq++)
			{
				CExpression *pexprSubq = (*pdrgpexprSubqs)[ulSubq];
				pexprSubq->AddRef();
				CColRef *colref = CScalarProjectElement::PopConvert((*pexprPrjList)[ulSubq]->Pop())->Pcr();
	#ifdef GPOS_DEBUG
				BOOL fInserted =
	#endif // GPOS_DEBUG
					phmexprcr->Insert(pexprSubq, colref);
				GPOS_ASSERT(fInserted);
			}

			// unnest subqueries in newly created child
			CExpression *pexprUnnested = PexprSubqueryUnnest(mp, pexprNewChild, fEnforceCorrelatedApply);
			if (NULL != pexprUnnested)
			{
				pexprNewChild->Release();
				pexprNewChild = pexprUnnested;
			}
		}

		pdrgpexprNewChildren->Append(pexprNewChild);
	}

	join_pred_expr->AddRef();
	pdrgpexprNewChildren->Append(join_pred_expr);

	// replace subqueries in the original scalar expression with
	// scalar identifiers based on constructed map
	CExpression *pexprNewScalar = PexprReplaceSubqueries(mp, pexprScalar, phmexprcr);

	phmexprcr->Release();
	pdrgpcrs->Release();
	pdrgpdrgpexprSubqs->Release();

	// build the new join expression
	COperator *pop = pexprJoin->Pop();
	pop->AddRef();
	CExpression *pexprNewJoin = GPOS_NEW(mp) CExpression(mp, pop, pdrgpexprNewChildren);

	// return a new Select expression
	pop = pexpr->Pop();
	pop->AddRef();
	return GPOS_NEW(mp) CExpression(mp, pop, pexprNewJoin, pexprNewScalar);
}
コード例 #23
0
//---------------------------------------------------------------------------
//	@function:
//		CXformSubqJoin2Apply::Transform
//
//	@doc:
//		Helper of transformation function
//
//---------------------------------------------------------------------------
void
CXformSubqJoin2Apply::Transform
	(
	CXformContext *pxfctxt,
	CXformResult *pxfres,
	CExpression *pexpr,
	BOOL fEnforceCorrelatedApply
	)
	const
{
	GPOS_ASSERT(NULL != pxfctxt);
	GPOS_ASSERT(FPromising(pxfctxt->Pmp(), this, pexpr));
	GPOS_ASSERT(FCheckPattern(pexpr));

	IMemoryPool *mp = pxfctxt->Pmp();
	CExpression *pexprSelect = CXformUtils::PexprSeparateSubqueryPreds(mp, pexpr);

	// attempt pushing subqueries to join children,
	// this optimization may not always succeed since unnested subqueries below joins
	// could hide columns needed to evaluate join condition
	CExpression *pexprSubqsPushedDown = PexprSubqueryPushDown(mp, pexprSelect, fEnforceCorrelatedApply);

	// check if join columns in join condition are still accessible after subquery pushdown
	CExpression *pexprJoin = (*pexprSubqsPushedDown)[0];
	CExpression *pexprJoinCondition = (*pexprJoin)[pexprJoin->Arity() - 1];
	CColRefSet *pcrsUsed = CDrvdPropScalar::GetDrvdScalarProps(pexprJoinCondition->PdpDerive())->PcrsUsed();
	CColRefSet *pcrsJoinOutput = CDrvdPropRelational::GetRelationalProperties(pexprJoin->PdpDerive())->PcrsOutput();
	if (!pcrsJoinOutput->ContainsAll(pcrsUsed))
	{
		// discard expression after subquery push down
		pexprSubqsPushedDown->Release();
		pexprSelect->AddRef();
		pexprSubqsPushedDown = pexprSelect;
	}

	pexprSelect->Release();

	CExpression *pexprResult = NULL;
	BOOL fHasSubquery = CDrvdPropScalar::GetDrvdScalarProps((*pexprSubqsPushedDown)[1]->PdpDerive())->FHasSubquery();
	if (fHasSubquery)
	{
		// unnest subqueries remaining in the top Select expression
		pexprResult = PexprSubqueryUnnest(mp, pexprSubqsPushedDown, fEnforceCorrelatedApply);
		pexprSubqsPushedDown->Release();
	}
	else
	{
		pexprResult = pexprSubqsPushedDown;
	}

	if (NULL == pexprResult)
	{
		// unnesting failed, return here
		return;
	}

	// normalize resulting expression and add it to xform results container
	CExpression *pexprNormalized = CNormalizer::PexprNormalize(mp, pexprResult);
	pexprResult->Release();
	pxfres->Add(pexprNormalized);
}
コード例 #24
0
ファイル: CPhysicalJoin.cpp プロジェクト: d/gporca
//---------------------------------------------------------------------------
//	@function:
//		CPhysicalJoin::AddHashKeys
//
//	@doc:
//		Helper for adding a pair of hash join keys to given arrays
//
//---------------------------------------------------------------------------
void
CPhysicalJoin::AddHashKeys
	(
	CExpression *pexprPred,	// equality predicate in the form (ColRef1 = ColRef2) or
							// in the form (ColRef1 is not distinct from ColRef2)
	CExpression *pexprOuter,
	CExpression *
#ifdef GPOS_DEBUG
		pexprInner
#endif // GPOS_DEBUG
	,
	DrgPexpr *pdrgpexprOuter,	// array of outer hash keys
	DrgPexpr *pdrgpexprInner	// array of inner hash keys
	)
{
	GPOS_ASSERT(FHashJoinCompatible(pexprPred, pexprOuter, pexprInner));

	// output of outer side
	CColRefSet *pcrsOuter = CDrvdPropRelational::Pdprel(pexprOuter->PdpDerive())->PcrsOutput();

#ifdef GPOS_DEBUG
	// output of inner side
	CColRefSet *pcrsInner = CDrvdPropRelational::Pdprel(pexprInner->PdpDerive())->PcrsOutput();
#endif // GPOS_DEBUG

	// extract outer and inner columns from predicate
	CExpression *pexprPredOuter = NULL;
	CExpression *pexprPredInner = NULL;
	ExtractHashJoinExpressions(pexprPred, &pexprPredOuter, &pexprPredInner);
	GPOS_ASSERT(NULL != pexprPredOuter);
	GPOS_ASSERT(NULL != pexprPredInner);

	CColRefSet *pcrsPredOuter = CDrvdPropScalar::Pdpscalar(pexprPredOuter->PdpDerive())->PcrsUsed();
#ifdef GPOS_DEBUG
	CColRefSet *pcrsPredInner = CDrvdPropScalar::Pdpscalar(pexprPredInner->PdpDerive())->PcrsUsed();
#endif // GPOS_DEBUG

	// determine outer and inner hash keys
	CExpression *pexprKeyOuter = NULL;
	CExpression *pexprKeyInner = NULL;
	if (pcrsOuter->FSubset(pcrsPredOuter))
	{
		pexprKeyOuter = pexprPredOuter;
		GPOS_ASSERT(pcrsInner->FSubset(pcrsPredInner));

		pexprKeyInner = pexprPredInner;
	}
	else
	{
		GPOS_ASSERT(pcrsOuter->FSubset(pcrsPredInner));
		pexprKeyOuter = pexprPredInner;

		GPOS_ASSERT(pcrsInner->FSubset(pcrsPredOuter));
		pexprKeyInner = pexprPredOuter;
	}
	pexprKeyOuter->AddRef();
	pexprKeyInner->AddRef();

	pdrgpexprOuter->Append(pexprKeyOuter);
	pdrgpexprInner->Append(pexprKeyInner);

	GPOS_ASSERT(pdrgpexprInner->UlLength() == pdrgpexprOuter->UlLength());
}
コード例 #25
0
//---------------------------------------------------------------------------
//	@function:
//		CXformJoinAssociativity::CreatePredicates
//
//	@doc:
//		Extract all conjuncts and divvy them up between upper and lower join
//
//---------------------------------------------------------------------------
void
CXformJoinAssociativity::CreatePredicates
	(
	IMemoryPool *pmp,
	CExpression *pexpr,
	DrgPexpr *pdrgpexprLower,
	DrgPexpr *pdrgpexprUpper
	)
	const
{
	GPOS_CHECK_ABORT;

	// bind operators
	CExpression *pexprLeft = (*pexpr)[0];
	CExpression *pexprLeftLeft = (*pexprLeft)[0];
	CExpression *pexprRight = (*pexpr)[1];
	
	DrgPexpr *pdrgpexprJoins = GPOS_NEW(pmp) DrgPexpr(pmp);

	pexprLeft->AddRef();
	pdrgpexprJoins->Append(pexprLeft);
	
	pexpr->AddRef();
	pdrgpexprJoins->Append(pexpr);	
	
	// columns for new lower join
	CColRefSet *pcrsLower = GPOS_NEW(pmp) CColRefSet(pmp);
	pcrsLower->Union(CDrvdPropRelational::Pdprel(pexprLeftLeft->PdpDerive())->PcrsOutput());
	pcrsLower->Union(CDrvdPropRelational::Pdprel(pexprRight->PdpDerive())->PcrsOutput());
	
	// convert current predicates into arrays of conjuncts
	DrgPexpr *pdrgpexprOrig = GPOS_NEW(pmp) DrgPexpr(pmp);
	
	for (ULONG ul = 0; ul < 2; ul++)
	{
		DrgPexpr *pdrgpexprPreds = CPredicateUtils::PdrgpexprConjuncts(pmp, (*(*pdrgpexprJoins)[ul])[2]);
		ULONG ulLen = pdrgpexprPreds->UlLength();
		for (ULONG ulConj = 0; ulConj < ulLen; ulConj++)
		{	
			CExpression *pexprConj = (*pdrgpexprPreds)[ulConj];
			pexprConj->AddRef();
			
			pdrgpexprOrig->Append(pexprConj);
		}
		pdrgpexprPreds->Release();
	}

	// divvy up conjuncts for upper and lower join
	ULONG ulConj = pdrgpexprOrig->UlLength();
	for (ULONG ul = 0; ul < ulConj; ul++)
	{
		CExpression *pexprPred = (*pdrgpexprOrig)[ul];
		CColRefSet *pcrs = CDrvdPropScalar::Pdpscalar(pexprPred->PdpDerive())->PcrsUsed();
		
		pexprPred->AddRef();
		if (pcrsLower->FSubset(pcrs))
		{
			pdrgpexprLower->Append(pexprPred);
		}
		else 
		{
			pdrgpexprUpper->Append(pexprPred);			
		}
	}
	
	// No predicates indicate a cross join. And for that, ORCA expects
	// predicate to be a scalar const "true".
	if (pdrgpexprLower->UlLength() == 0)
	{
		CExpression *pexprCrossLowerJoinPred = CUtils::PexprScalarConstBool(pmp, true, false);
		pdrgpexprLower->Append(pexprCrossLowerJoinPred);
	}
	
	// Same for upper predicates
	if (pdrgpexprUpper->UlLength() == 0)
	{
		CExpression *pexprCrossUpperJoinPred = CUtils::PexprScalarConstBool(pmp, true, false);
		pdrgpexprUpper->Append(pexprCrossUpperJoinPred);
	}

	// clean up
	pcrsLower->Release();
	pdrgpexprOrig->Release();
	
	pdrgpexprJoins->Release();
}
コード例 #26
0
ファイル: CCostTest.cpp プロジェクト: b-xiang/gporca
//---------------------------------------------------------------------------
//	@function:
//		CCostTest::EresUnittest_SetParams
//
//	@doc:
//		Test of setting cost model params
//
//---------------------------------------------------------------------------
GPOS_RESULT
CCostTest::EresUnittest_SetParams()
{
	CAutoMemoryPool amp;
	IMemoryPool *mp = amp.Pmp();

	// setup a file-based provider
	CMDProviderMemory *pmdp = CTestUtils::m_pmdpf;
	pmdp->AddRef();
	CMDAccessor mda(mp, CMDCache::Pcache(), CTestUtils::m_sysidDefault, pmdp);

	ICostModel *pcm = GPOS_NEW(mp) CCostModelGPDB(mp, GPOPT_TEST_SEGMENTS);

	// install opt context in TLS
	CAutoOptCtxt aoc(mp, &mda, NULL, /* pceeval */ pcm);

	// generate in-equality join expression
	CExpression *pexprOuter = CTestUtils::PexprLogicalGet(mp);
	const CColRef *pcrOuter = CDrvdPropRelational::GetRelationalProperties(pexprOuter->PdpDerive())->PcrsOutput()->PcrAny();
	CExpression *pexprInner = CTestUtils::PexprLogicalGet(mp);
	const CColRef *pcrInner = CDrvdPropRelational::GetRelationalProperties(pexprInner->PdpDerive())->PcrsOutput()->PcrAny();
	CExpression *pexprPred = CUtils::PexprScalarCmp(mp, pcrOuter, pcrInner, IMDType::EcmptNEq);
	CExpression *pexpr = CUtils::PexprLogicalJoin<CLogicalInnerJoin>(mp, pexprOuter, pexprInner, pexprPred);

	// optimize in-equality join based on default cost model params
	CExpression *pexprPlan1 = NULL;
	{
		CEngine eng(mp);

		// generate query context
		CQueryContext *pqc = CTestUtils::PqcGenerate(mp, pexpr);

		// Initialize engine
		eng.Init(pqc, NULL /*search_stage_array*/);

		// optimize query
		eng.Optimize();

		// extract plan
		pexprPlan1 = eng.PexprExtractPlan();
		GPOS_ASSERT(NULL != pexprPlan1);

		GPOS_DELETE(pqc);
	}

	// change NLJ cost factor
	ICostModelParams::SCostParam *pcp = pcm->GetCostModelParams()->PcpLookup(CCostModelParamsGPDB::EcpNLJFactor);
	CDouble dNLJFactor = CDouble(2.0);
	CDouble dVal = pcp->Get() * dNLJFactor;
	pcm->GetCostModelParams()->SetParam(pcp->Id(), dVal, dVal - 0.5, dVal + 0.5);

	// optimize again after updating NLJ cost factor
	CExpression *pexprPlan2 = NULL;
	{
		CEngine eng(mp);

		// generate query context
		CQueryContext *pqc = CTestUtils::PqcGenerate(mp, pexpr);

		// Initialize engine
		eng.Init(pqc, NULL /*search_stage_array*/);

		// optimize query
		eng.Optimize();

		// extract plan
		pexprPlan2 = eng.PexprExtractPlan();
		GPOS_ASSERT(NULL != pexprPlan2);

		GPOS_DELETE(pqc);
	}

	{
		CAutoTrace at(mp);
		at.Os() << "\nPLAN1: \n" << *pexprPlan1;
		at.Os() << "\nNLJ Cost1: " << (*pexprPlan1)[0]->Cost();
		at.Os() << "\n\nPLAN2: \n" << *pexprPlan2;
		at.Os() << "\nNLJ Cost2: " << (*pexprPlan2)[0]->Cost();
	}
	GPOS_ASSERT((*pexprPlan2)[0]->Cost() >= (*pexprPlan1)[0]->Cost() * dNLJFactor &&
			"expected NLJ cost in PLAN2 to be larger than NLJ cost in PLAN1");

	// clean up
	pexpr->Release();
	pexprPlan1->Release();
	pexprPlan2->Release();

	return GPOS_OK;
}
コード例 #27
0
//---------------------------------------------------------------------------
//	@function:
//		CPredicateUtilsTest::EresUnittest_Conjunctions
//
//	@doc:
//		Test extraction and construction of conjuncts
//
//---------------------------------------------------------------------------
GPOS_RESULT
CPredicateUtilsTest::EresUnittest_Conjunctions()
{
	CAutoMemoryPool amp;
	IMemoryPool *mp = amp.Pmp();

	// setup a file-based provider
	CMDProviderMemory *pmdp = CTestUtils::m_pmdpf;
	pmdp->AddRef();
	CMDAccessor mda(mp, CMDCache::Pcache(), CTestUtils::m_sysidDefault, pmdp);

	// install opt context in TLS
	CAutoOptCtxt aoc
					(
					mp,
					&mda,
					NULL,  /* pceeval */
					CTestUtils::GetCostModel(mp)
					);

	// build conjunction
	CExpressionArray *pdrgpexpr = GPOS_NEW(mp) CExpressionArray(mp);
	const ULONG ulConjs = 3;
	for (ULONG ul = 0; ul < ulConjs; ul++)
	{
		pdrgpexpr->Append(CUtils::PexprScalarConstBool(mp, true /*fValue*/));
	}
	CExpression *pexprConjunction = CUtils::PexprScalarBoolOp(mp, CScalarBoolOp::EboolopAnd, pdrgpexpr);
	
	// break into conjuncts
	CExpressionArray *pdrgpexprExtract = CPredicateUtils::PdrgpexprConjuncts(mp, pexprConjunction);
	GPOS_ASSERT(pdrgpexprExtract->Size() == ulConjs);
	
	// collapse into single conjunct
	CExpression *pexpr = CPredicateUtils::PexprConjunction(mp, pdrgpexprExtract);
	GPOS_ASSERT(NULL != pexpr);
	GPOS_ASSERT(CUtils::FScalarConstTrue(pexpr));
	pexpr->Release();
	
	// collapse empty input array to conjunct
	CExpression *pexprSingleton = CPredicateUtils::PexprConjunction(mp, NULL /*pdrgpexpr*/);
	GPOS_ASSERT(NULL != pexprSingleton);
	pexprSingleton->Release();

	pexprConjunction->Release();

	// conjunction on scalar comparisons
	CExpression *pexprGet = CTestUtils::PexprLogicalGet(mp);
	CColRefSet *pcrs = CDrvdPropRelational::GetRelationalProperties(pexprGet->PdpDerive())->PcrsOutput();
	CColRef *pcr1 = pcrs->PcrAny();
	CColRef *pcr2 = pcrs->PcrFirst();
	CExpression *pexprCmp1 = CUtils::PexprScalarCmp(mp, pcr1, pcr2, IMDType::EcmptEq);
	CExpression *pexprCmp2 = CUtils::PexprScalarCmp(mp, pcr1, CUtils::PexprScalarConstInt4(mp, 1 /*val*/), IMDType::EcmptEq);

	CExpression *pexprConj = CPredicateUtils::PexprConjunction(mp, pexprCmp1, pexprCmp2);
	pdrgpexprExtract = CPredicateUtils::PdrgpexprConjuncts(mp, pexprConj);
	GPOS_ASSERT(2 == pdrgpexprExtract->Size());
	pdrgpexprExtract->Release();

	pexprCmp1->Release();
	pexprCmp2->Release();
	pexprConj->Release();
	pexprGet->Release();

	return GPOS_OK;
}
コード例 #28
0
//---------------------------------------------------------------------------
//	@function:
//		CPredicateUtilsTest::EresUnittest_PlainEqualities
//
//	@doc:
//		Test the extraction of equality predicates between scalar identifiers
//
//---------------------------------------------------------------------------
GPOS_RESULT
CPredicateUtilsTest::EresUnittest_PlainEqualities()
{
	CAutoMemoryPool amp;
	IMemoryPool *mp = amp.Pmp();

	// setup a file-based provider
	CMDProviderMemory *pmdp = CTestUtils::m_pmdpf;
	pmdp->AddRef();
	CMDAccessor mda(mp, CMDCache::Pcache(), CTestUtils::m_sysidDefault, pmdp);

	// install opt context in TLS
	CAutoOptCtxt aoc
					(
					mp,
					&mda,
					NULL,  /* pceeval */
					CTestUtils::GetCostModel(mp)
					);

	CExpression *pexprLeft = CTestUtils::PexprLogicalGet(mp);
	CExpression *pexprRight = CTestUtils::PexprLogicalGet(mp);

	CExpressionArray *pdrgpexprOriginal = GPOS_NEW(mp) CExpressionArray(mp);

	CColRefSet *pcrsLeft = CDrvdPropRelational::GetRelationalProperties(pexprLeft->PdpDerive())->PcrsOutput();
	CColRefSet *pcrsRight = CDrvdPropRelational::GetRelationalProperties(pexprRight->PdpDerive())->PcrsOutput();

	CColRef *pcrLeft = pcrsLeft->PcrAny();
	CColRef *pcrRight = pcrsRight->PcrAny();

	// generate an equality predicate between two column reference
	CExpression *pexprScIdentEquality =
		CUtils::PexprScalarEqCmp(mp, pcrLeft, pcrRight);

	pexprScIdentEquality->AddRef();
	pdrgpexprOriginal->Append(pexprScIdentEquality);

	// generate a non-equality predicate between two column reference
	CExpression *pexprScIdentInequality =
		CUtils::PexprScalarCmp(mp, pcrLeft, pcrRight, CWStringConst(GPOS_WSZ_LIT("<")), GPOS_NEW(mp) CMDIdGPDB(GPDB_INT4_LT_OP));

	pexprScIdentInequality->AddRef();
	pdrgpexprOriginal->Append(pexprScIdentInequality);

	// generate an equality predicate between a column reference and a constant value
	CExpression *pexprScalarConstInt4 = CUtils::PexprScalarConstInt4(mp, 10 /*fValue*/);
	CExpression *pexprScIdentConstEquality = CUtils::PexprScalarEqCmp(mp, pexprScalarConstInt4, pcrRight);

	pdrgpexprOriginal->Append(pexprScIdentConstEquality);

	GPOS_ASSERT(3 == pdrgpexprOriginal->Size());

	CExpressionArray *pdrgpexprResult = CPredicateUtils::PdrgpexprPlainEqualities(mp, pdrgpexprOriginal);

	GPOS_ASSERT(1 == pdrgpexprResult->Size());

	// clean up
	pdrgpexprOriginal->Release();
	pdrgpexprResult->Release();
	pexprLeft->Release();
	pexprRight->Release();
	pexprScIdentEquality->Release();
	pexprScIdentInequality->Release();

	return GPOS_OK;
}
コード例 #29
0
ファイル: CDecorrelator.cpp プロジェクト: HanumathRao/gporca
//---------------------------------------------------------------------------
//	@function:
//		CDecorrelator::FProcessPredicate
//
//	@doc:
//		Decorrelate predicate
//
//---------------------------------------------------------------------------
BOOL
CDecorrelator::FProcessPredicate
	(
	IMemoryPool *pmp,
	CExpression *pexprLogical, // logical parent of predicate tree
	CExpression *pexprScalar,
	BOOL fEqualityOnly,
	CColRefSet *pcrsOutput,
	CExpression **ppexprDecorrelated,
	DrgPexpr *pdrgpexprCorrelations
	)
{
	GPOS_ASSERT(pexprLogical->Pop()->FLogical());
	GPOS_ASSERT(pexprScalar->Pop()->FScalar());

	*ppexprDecorrelated = NULL;
	
	DrgPexpr *pdrgpexprConj = CPredicateUtils::PdrgpexprConjuncts(pmp, pexprScalar);
	DrgPexpr *pdrgpexprResiduals = GPOS_NEW(pmp) DrgPexpr(pmp);
	BOOL fSuccess = true;
	
	// divvy up the predicates in residuals (w/ no outer ref) and correlations (w/ outer refs)
	ULONG ulLength = pdrgpexprConj->UlLength();
	for(ULONG ul = 0; ul < ulLength && fSuccess; ul++)
	{
		CExpression *pexprConj = (*pdrgpexprConj)[ul];
		CColRefSet *pcrsUsed = CDrvdPropScalar::Pdpscalar(pexprConj->PdpDerive())->PcrsUsed();
		
		if (pcrsOutput->FSubset(pcrsUsed))
		{
			// no outer ref
			pexprConj->AddRef();
			pdrgpexprResiduals->Append(pexprConj);			

			continue;
		}
		
		fSuccess = FDelayable(pexprLogical, pexprConj, fEqualityOnly);
		if (fSuccess)
		{
			pexprConj->AddRef();
			pdrgpexprCorrelations->Append(pexprConj);
		}
		
	}

	pdrgpexprConj->Release();

	if (!fSuccess || 0 == pdrgpexprResiduals->UlLength())
	{
		// clean up
		pdrgpexprResiduals->Release();
	}
	else
	{
		// residuals become new predicate
		*ppexprDecorrelated = CPredicateUtils::PexprConjunction(pmp, pdrgpexprResiduals);
	}


	return fSuccess;
}
コード例 #30
0
ファイル: CDecorrelator.cpp プロジェクト: HanumathRao/gporca
//---------------------------------------------------------------------------
//	@function:
//		CDecorrelator::FProcessJoin
//
//	@doc:
//		Decorrelate a join expression;
//
//---------------------------------------------------------------------------
BOOL
CDecorrelator::FProcessJoin
	(
	IMemoryPool *pmp,
	CExpression *pexpr,
	BOOL fEqualityOnly,
	CExpression **ppexprDecorrelated,
	DrgPexpr *pdrgpexprCorrelations
	)
{
	GPOS_ASSERT(CUtils::FLogicalJoin(pexpr->Pop()) || CUtils::FApply(pexpr->Pop()));

	ULONG ulArity = pexpr->UlArity();	
	DrgPexpr *pdrgpexpr = GPOS_NEW(pmp) DrgPexpr(pmp, ulArity);
	CColRefSet *pcrsOutput = GPOS_NEW(pmp) CColRefSet(pmp);

	// decorrelate all relational children
	for (ULONG ul = 0; ul < ulArity - 1; ul++)
	{
		CExpression *pexprInput = NULL;
		if (FProcess(pmp, (*pexpr)[ul], fEqualityOnly, &pexprInput, pdrgpexprCorrelations))
		{
			pdrgpexpr->Append(pexprInput);
			pcrsOutput->Union(CDrvdPropRelational::Pdprel(pexprInput->PdpDerive())->PcrsOutput());
		}
		else
		{
			pdrgpexpr->Release();
			pcrsOutput->Release();
			
			return false;
		}
	}

	// check for valid semi join correlations
	if (!FPullableCorrelations(pmp, pexpr, pdrgpexpr, pdrgpexprCorrelations))
	{
		pdrgpexpr->Release();
		pcrsOutput->Release();

		return false;
	 }

	// decorrelate predicate and build new join operator
	CExpression *pexprPredicate = NULL;
	BOOL fSuccess = FProcessPredicate(pmp, pexpr, (*pexpr)[ulArity - 1], fEqualityOnly, pcrsOutput, &pexprPredicate, pdrgpexprCorrelations);
	pcrsOutput->Release();

	if (fSuccess)
	{
		// in case entire predicate is being deferred, plug in a 'true'
		if (NULL == pexprPredicate)
		{
			pexprPredicate = CUtils::PexprScalarConstBool(pmp, true /*fVal*/);
		}
		
		pdrgpexpr->Append(pexprPredicate);
		
		COperator *pop = pexpr->Pop();
		pop->AddRef();
		*ppexprDecorrelated = GPOS_NEW(pmp) CExpression(pmp, pop, pdrgpexpr);
	}
	else
	{
		pdrgpexpr->Release();
		CRefCount::SafeRelease(pexprPredicate);
	}
	
	return fSuccess;
}