Beispiel #1
0
//---------------------------------------------------------------------------
//	@function:
//		CXformTest::ApplyExprXforms
//
//	@doc:
//		Apply different xforms for the given expression
//
//---------------------------------------------------------------------------
void
CXformTest::ApplyExprXforms
	(
	IMemoryPool *pmp,
	IOstream &os,
	CExpression *pexpr
	)
{
	os << std::endl << "EXPR:" << std::endl;
	(void) pexpr->OsPrint(os);

	for (ULONG ulXformId = 0; ulXformId < CXform::ExfSentinel; ulXformId++)
	{
		CXform *pxform = CXformFactory::Pxff()->Pxf((CXform::EXformId) ulXformId);
		os << std::endl <<"XFORM " << pxform->SzId() << ":" << std::endl;

		CXformContext *pxfctxt = GPOS_NEW(pmp) CXformContext(pmp);
		CXformResult *pxfres = GPOS_NEW(pmp) CXformResult(pmp);

#ifdef GPOS_DEBUG
		if (pxform->FCheckPattern(pexpr) && CXform::FPromising(pmp, pxform, pexpr))
		{
			if (CXform::ExfExpandNAryJoinMinCard == pxform->Exfid())
			{
				GPOS_ASSERT(COperator::EopLogicalNAryJoin == pexpr->Pop()->Eopid());

				// derive stats on NAry join expression
				CExpressionHandle exprhdl(pmp);
				exprhdl.Attach(pexpr);
				exprhdl.DeriveStats(pmp, pmp, NULL /*prprel*/, NULL /*pdrgpstatCtxt*/);
			}

			pxform->Transform(pxfctxt, pxfres, pexpr);

			CExpression *pexprResult = pxfres->PexprNext();
			while (NULL != pexprResult)
			{
				GPOS_ASSERT(pexprResult->FMatchDebug(pexprResult));

				pexprResult = pxfres->PexprNext();
			}
			(void) pxfres->OsPrint(os);
		}
#endif // GPOS_DEBUG

		pxfres->Release();
		pxfctxt->Release();
	}
}
//---------------------------------------------------------------------------
//	@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:
//		CSubqueryHandlerTest::EresUnittest_Subquery2Apply
//
//	@doc:
//		Test of subquery handler
//
//---------------------------------------------------------------------------
GPOS_RESULT
CSubqueryHandlerTest::EresUnittest_Subquery2Apply()
{
	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);
	
	typedef CExpression *(*Pfpexpr)(IMemoryPool*, BOOL);
	Pfpexpr rgpf[] =
		{
		CSubqueryTestUtils::PexprSelectWithAggSubquery,
		CSubqueryTestUtils::PexprSelectWithAggSubqueryConstComparison,
		CSubqueryTestUtils::PexprProjectWithAggSubquery,
		CSubqueryTestUtils::PexprSelectWithAnySubquery,
		CSubqueryTestUtils::PexprProjectWithAnySubquery,
		CSubqueryTestUtils::PexprSelectWithAllSubquery,
		CSubqueryTestUtils::PexprProjectWithAllSubquery,
		CSubqueryTestUtils::PexprSelectWithExistsSubquery,
		CSubqueryTestUtils::PexprProjectWithExistsSubquery,
		CSubqueryTestUtils::PexprSelectWithNotExistsSubquery,
		CSubqueryTestUtils::PexprProjectWithNotExistsSubquery,
		CSubqueryTestUtils::PexprSelectWithNestedCmpSubquery,
		CSubqueryTestUtils::PexprSelectWithCmpSubqueries,
		CSubqueryTestUtils::PexprSelectWithSubqueryConjuncts,
		CSubqueryTestUtils::PexprProjectWithSubqueries,
		CSubqueryTestUtils::PexprSelectWith2LevelsCorrSubquery,
		CSubqueryTestUtils::PexprJoinWithAggSubquery,
		CSubqueryTestUtils::PexprSelectWithAggSubqueryOverJoin,
		CSubqueryTestUtils::PexprSelectWithNestedSubquery,
		CSubqueryTestUtils::PexprSubqueriesInNullTestContext,
		CSubqueryTestUtils::PexprSubqueriesInDifferentContexts,
		CSubqueryTestUtils::PexprSelectWithSubqueryDisjuncts,
		CSubqueryTestUtils::PexprSelectWithNestedAnySubqueries,
		CSubqueryTestUtils::PexprSelectWithNestedAllSubqueries,
		CSubqueryTestUtils::PexprUndecorrelatableAnySubquery,
		CSubqueryTestUtils::PexprUndecorrelatableAllSubquery,
		CSubqueryTestUtils::PexprUndecorrelatableExistsSubquery,
		CSubqueryTestUtils::PexprUndecorrelatableNotExistsSubquery,
		CSubqueryTestUtils::PexprUndecorrelatableScalarSubquery,
		};

	// xforms to test
	CXformSet *xform_set = GPOS_NEW(mp) CXformSet(mp);
	(void) xform_set->ExchangeSet(CXform::ExfSubqJoin2Apply);
	(void) xform_set->ExchangeSet(CXform::ExfSelect2Apply);
	(void) xform_set->ExchangeSet(CXform::ExfProject2Apply);

	BOOL fCorrelated = true;
	// we generate two expressions using each generator
	const ULONG size = 2 * GPOS_ARRAY_SIZE(rgpf);
	for (ULONG ul = 0; ul < size; ul++)
	{
		ULONG ulIndex = ul / 2;
		// install opt context in TLS
		CAutoOptCtxt aoc
					(
					mp,
					&mda,
					NULL,  /* pceeval */
					CTestUtils::GetCostModel(mp)
					);

		// generate expression
		CExpression *pexpr = rgpf[ulIndex](mp, fCorrelated);
		
		// check for subq xforms
		CXformSet *pxfsCand = CLogical::PopConvert(pexpr->Pop())->PxfsCandidates(mp);
		pxfsCand->Intersection(xform_set);
		
		CXformSetIter xsi(*pxfsCand);
		while (xsi.Advance())
		{			
			CXform *pxform = CXformFactory::Pxff()->Pxf(xsi.TBit());
			GPOS_ASSERT(NULL != pxform);

			CWStringDynamic str(mp);
			COstreamString oss(&str);

			oss	<< std::endl << "INPUT:" << std::endl << *pexpr << std::endl;

			CXformContext *pxfctxt = GPOS_NEW(mp) CXformContext(mp);
			CXformResult *pxfres = GPOS_NEW(mp) CXformResult(mp);

			// calling the xform to perform subquery to Apply transformation
			pxform->Transform(pxfctxt, pxfres, pexpr);
			CExpression *pexprResult = pxfres->PexprNext();

			oss	<< std::endl << "OUTPUT:" << std::endl;
			if (NULL != pexprResult)
			{
				oss << *pexprResult << std::endl;
			}
			else
			{
				oss << "\tNo subquery unnesting output" << std::endl;
			}

			GPOS_TRACE(str.GetBuffer());
			str.Reset();

			pxfres->Release();
			pxfctxt->Release();
		}
		
		pxfsCand->Release();
		pexpr->Release();
		fCorrelated = !fCorrelated;
	}

	xform_set->Release();

	return GPOS_OK;
}
//---------------------------------------------------------------------------
//	@function:
//		CSubqueryHandlerTest::EresUnittest_SubqueryWithDisjunction
//
//	@doc:
//		Test case of subqueries in a disjunctive tree
//
//---------------------------------------------------------------------------
GPOS_RESULT
CSubqueryHandlerTest::EresUnittest_SubqueryWithDisjunction()
{
	// use own memory pool
	CAutoMemoryPool amp(CAutoMemoryPool::ElcNone);
	IMemoryPool *mp = amp.Pmp();

	// setup a file-based provider
	CMDProviderMemory *pmdp = CTestUtils::m_pmdpf;
	pmdp->AddRef();
	CMDAccessor mda(mp, CMDCache::Pcache());
	mda.RegisterProvider(CTestUtils::m_sysidDefault, pmdp);
	
	// install opt context in TLS
	CAutoOptCtxt aoc
					(
					mp,
					&mda,
					NULL,  /* pceeval */
					CTestUtils::GetCostModel(mp)
					);
		
	// create a subquery with const table get expression

	CExpression *pexprOuter = NULL;
	CExpression *pexprInner = NULL;
	CSubqueryTestUtils::GenerateGetExpressions(mp, &pexprOuter, &pexprInner);

	CExpression *pexpr = CSubqueryTestUtils::PexprSelectWithSubqueryBoolOp(mp, pexprOuter, pexprInner, true /*fCorrelated*/, CScalarBoolOp::EboolopOr);
	
	CXform *pxform = CXformFactory::Pxff()->Pxf(CXform::ExfSelect2Apply);

	CWStringDynamic str(mp);
	COstreamString oss(&str);

	oss	<< std::endl << "EXPRESSION:" << std::endl << *pexpr << std::endl;

	CExpression *pexprLogical = (*pexpr)[0];
	CExpression *pexprScalar = (*pexpr)[1];
	oss	<< std::endl << "LOGICAL:" << std::endl << *pexprLogical << std::endl;
	oss	<< std::endl << "SCALAR:" << std::endl << *pexprScalar << std::endl;

	GPOS_TRACE(str.GetBuffer());
	str.Reset();

	CXformContext *pxfctxt = GPOS_NEW(mp) CXformContext(mp);
	CXformResult *pxfres = GPOS_NEW(mp) CXformResult(mp);

	// calling the xform to perform subquery to Apply transformation
	pxform->Transform(pxfctxt, pxfres, pexpr);
	CExpression *pexprResult = pxfres->PexprNext();
	
	oss	<< std::endl << "NEW LOGICAL:" << std::endl << *((*pexprResult)[0]) << std::endl;
	oss	<< std::endl << "RESIDUAL SCALAR:" << std::endl << *((*pexprResult)[1]) << std::endl;

	GPOS_TRACE(str.GetBuffer());
	str.Reset();

	pxfres->Release();
	pxfctxt->Release();
	pexpr->Release();

	return GPOS_OK;
}
//---------------------------------------------------------------------------
//	@function:
//		CSubqueryHandlerTest::EresUnittest_SubqueryWithConstSubqueries
//
//	@doc:
//		Test of subquery handler for ALL subquery over const table get
//
//---------------------------------------------------------------------------
GPOS_RESULT
CSubqueryHandlerTest::EresUnittest_SubqueryWithConstSubqueries()
{
	CAutoMemoryPool amp;
	IMemoryPool *mp = amp.Pmp();

	// setup a file-based provider
	CMDProviderMemory *pmdp = CTestUtils::m_pmdpf;
	pmdp->AddRef();
	
	// we need to use an auto pointer for the cache here to ensure
	// deleting memory of cached objects when we throw
	CAutoP<CMDAccessor::MDCache> apcache;
	apcache = CCacheFactory::CreateCache<gpopt::IMDCacheObject*, gpopt::CMDKey*>
					(
					true, // fUnique
					0 /* unlimited cache quota */,
					CMDKey::UlHashMDKey,
					CMDKey::FEqualMDKey
					);

	CMDAccessor::MDCache *pcache = apcache.Value();

	{
		CMDAccessor mda(mp, pcache, CTestUtils::m_sysidDefault, pmdp);

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

		// create a subquery with const table get expression
		CExpression *pexpr = CSubqueryTestUtils::PexprSubqueryWithDisjunction(mp);
		CXform *pxform = CXformFactory::Pxff()->Pxf(CXform::ExfSelect2Apply);

		CWStringDynamic str(mp);
		COstreamString oss(&str);

		oss	<< std::endl << "EXPRESSION:" << std::endl << *pexpr << std::endl;

		CExpression *pexprLogical = (*pexpr)[0];
		CExpression *pexprScalar = (*pexpr)[1];
		oss	<< std::endl << "LOGICAL:" << std::endl << *pexprLogical << std::endl;
		oss	<< std::endl << "SCALAR:" << std::endl << *pexprScalar << std::endl;

		GPOS_TRACE(str.GetBuffer());
		str.Reset();

		CXformContext *pxfctxt = GPOS_NEW(mp) CXformContext(mp);
		CXformResult *pxfres = GPOS_NEW(mp) CXformResult(mp);

		// calling the xform to perform subquery to Apply transformation;
		// xform must fail since we do not expect constant subqueries
		pxform->Transform(pxfctxt, pxfres, pexpr);
		CExpression *pexprResult = pxfres->PexprNext();
		
		oss	<< std::endl << "NEW LOGICAL:" << std::endl << *((*pexprResult)[0]) << std::endl;
		oss	<< std::endl << "RESIDUAL SCALAR:" << std::endl << *((*pexprResult)[1]) << std::endl;

		GPOS_TRACE(str.GetBuffer());
		str.Reset();

		pxfres->Release();
		pxfctxt->Release();
		pexpr->Release();
	
	}

	return GPOS_FAILED;
}