greenplumn CTreeMapTest 源码

  • 2022-08-18
  • 浏览 (184)

greenplumn CTreeMapTest 代码

文件路径:/src/backend/gporca/server/src/unittest/gpopt/search/CTreeMapTest.cpp

//---------------------------------------------------------------------------
//	Greenplum Database
//	Copyright (C) 2011 EMC Corp.
//
//	@filename:
//		CTreeMapTest.cpp
//
//	@doc:
//		Test of tree map facility
//---------------------------------------------------------------------------

#include "unittest/gpopt/search/CTreeMapTest.h"

#include "gpos/error/CAutoTrace.h"
#include "gpos/io/COstreamString.h"
#include "gpos/string/CWStringDynamic.h"
#include "gpos/task/CAutoTraceFlag.h"
#include "gpos/task/CTask.h"
#include "gpos/types.h"

#include "gpopt/base/CDrvdPropCtxtPlan.h"
#include "gpopt/engine/CEngine.h"
#include "gpopt/eval/CConstExprEvaluatorDefault.h"
#include "gpopt/exception.h"
#include "gpopt/operators/CLogicalInnerJoin.h"

#include "unittest/base.h"
#include "unittest/gpopt/CTestUtils.h"


ULONG CTreeMapTest::m_ulTestCounter = 0;  // start from first test


//---------------------------------------------------------------------------
// raw data for test
//---------------------------------------------------------------------------
const ULONG ulElems = 10;
static ULONG rgul[ulElems];


//---------------------------------------------------------------------------
//	@function:
//		CTreeMapTest::EresUnittest
//
//	@doc:
//		Unittest for state machine
//
//---------------------------------------------------------------------------
GPOS_RESULT
CTreeMapTest::EresUnittest()
{
	CUnittest rgut[] = {
		GPOS_UNITTEST_FUNC(CTreeMapTest::EresUnittest_Basic),
		GPOS_UNITTEST_FUNC(CTreeMapTest::EresUnittest_Count),
		GPOS_UNITTEST_FUNC(CTreeMapTest::EresUnittest_Unrank),
		GPOS_UNITTEST_FUNC(CTreeMapTest::EresUnittest_Memo),

#ifdef GPOS_DEBUG
		GPOS_UNITTEST_FUNC_ASSERT(CTreeMapTest::EresUnittest_Cycle),
#endif	// GPOS_DEBUG
	};

	return CUnittest::EresExecute(rgut, GPOS_ARRAY_SIZE(rgut));
}


//---------------------------------------------------------------------------
//	@function:
//		CTreeMapTest::CNode::OsPrint
//
//	@doc:
//		Debug print function
//
//---------------------------------------------------------------------------
IOstream &
CTreeMapTest::CNode::OsPrintWithIndent(IOstream &os, ULONG ulIndent) const
{
	for (ULONG ul = 0; ul < ulIndent; ul++)
	{
		os << " ";
	}
	os << "node: " << m_ulData << std::endl;

	for (ULONG ulChild = 0; ulChild < m_pdrgpnd->Size(); ulChild++)
	{
		(void) (*m_pdrgpnd)[ulChild]->OsPrintWithIndent(os, ulIndent + 2);
	}

	return os;
}


//---------------------------------------------------------------------------
//	@function:
//		CTreeMapTest::CNode::CNode
//
//	@doc:
//		ctor
//
//---------------------------------------------------------------------------
CTreeMapTest::CNode::CNode(CMemoryPool *,  // mp
						   const ULONG *pulData, CNodeArray *pdrgpnd)
	: m_ulData(gpos::ulong_max), m_pdrgpnd(pdrgpnd)
{
	if (nullptr != pulData)
	{
		m_ulData = *pulData;
	}
}


//---------------------------------------------------------------------------
//	@function:
//		CTreeMapTest::CNode::~CNode
//
//	@doc:
//		ctor
//
//---------------------------------------------------------------------------
CTreeMapTest::CNode::~CNode()
{
	CRefCount::SafeRelease(m_pdrgpnd);
}


//---------------------------------------------------------------------------
//	@function:
//		CTreeMapTest::Pnd
//
//	@doc:
//		Constructor function for result tree
//
//---------------------------------------------------------------------------
CTreeMapTest::CNode *
CTreeMapTest::Pnd(CMemoryPool *mp, ULONG *pul, CNodeArray *pdrgpnd,
				  BOOL *fTestTrue)
{
	// The test passes 'true' to PrUnrank and the rehydrate function expects to find it here.
	GPOS_ASSERT(nullptr != fTestTrue);
	GPOS_ASSERT(*fTestTrue && "Flag is expected to be true");
	*fTestTrue = true;
	return GPOS_NEW(mp) CNode(mp, pul, pdrgpnd);
}


//---------------------------------------------------------------------------
//	@function:
//		CTreeMapTest::PtmapLoad
//
//	@doc:
//		Create a semantically meaningful tree map by simulating a MEMO
//		layout
//
//---------------------------------------------------------------------------
CTreeMapTest::TestMap *
CTreeMapTest::PtmapLoad(CMemoryPool *mp)
{
	TestMap *ptmap = GPOS_NEW(mp) TestMap(mp, &Pnd);

	// init raw data
	for (ULONG pos = 0; pos < ulElems; pos++)
	{
		rgul[pos] = pos;
	}


	// simulate the following MEMO with individual edge insertions
	struct SEdge
	{
		// number of parent node
		ULONG m_ulParent;

		// position of child
		ULONG m_ulPos;

		// number of child node
		ULONG m_ulChild;
	} rgedge[] = {
		// root group: Join [4,3], HashJoin[4,3]{8}, HashJoin[3,4]{9}
		{9, 1, 7},
		{9, 0, 6},
		{9, 0, 5},
		{8, 0, 7},
		{8, 1, 5},
		{8, 1, 6},

		// group 4: C, TabScan{7}

		// group 3: Join[1,2], HashJoin[1,2]{5}, SortMergeJoin[1,2]{6}
		{5, 0, 0},
		{5, 0, 1},
		{5, 1, 2},
		{5, 1, 3},
		{5, 1, 4},
		{6, 0, 1},
		{6, 1, 3},
		{6, 1, 4},

		// group 2: B, TabScan{2}, IndexScan{3}, Sort[2]{4}
		{4, 0, 2}

		// group 1: A, TabScan{0}, IndexScan{1}
	};

	for (ULONG ul = 0; ul < GPOS_ARRAY_SIZE(rgedge); ul++)
	{
		SEdge &edge = rgedge[ul];
		ptmap->Insert(&rgul[edge.m_ulParent], edge.m_ulPos,
					  &rgul[edge.m_ulChild]);
	}

	return ptmap;
}


//---------------------------------------------------------------------------
//	@function:
//		CTreeMapTest::EresUnittest_Basic
//
//	@doc:
//		Basic test
//
//---------------------------------------------------------------------------
GPOS_RESULT
CTreeMapTest::EresUnittest_Basic()
{
	CAutoMemoryPool amp;
	CMemoryPool *mp = amp.Pmp();

	TestMap *ptmap = nullptr;

	// create blank map
	ptmap = GPOS_NEW(mp) TestMap(mp, &Pnd);
	GPOS_ASSERT(0 == ptmap->UllCount());
	GPOS_DELETE(ptmap);

	// create map with test data
	ptmap = PtmapLoad(mp);
	GPOS_DELETE(ptmap);

	return GPOS_OK;
}


//---------------------------------------------------------------------------
//	@function:
//		CTreeMapTest::EresUnittest_Count
//
//	@doc:
//		Count and debug output of all counts at various nodes
//
//---------------------------------------------------------------------------
GPOS_RESULT
CTreeMapTest::EresUnittest_Count()
{
	CAutoMemoryPool amp;
	CMemoryPool *mp = amp.Pmp();

	TestMap *ptmap = PtmapLoad(mp);

	// debug print
	CWStringDynamic str(mp);
	COstreamString oss(&str);

	ULLONG ullCount = ptmap->UllCount();
	oss << "total number of trees: " << ullCount << std::endl;

#ifdef GPOS_DEBUG

	for (ULONG ul = 0; ul < ulElems; ul++)
	{
		oss << "node: " << ul << " count: " << ptmap->UllCount(&rgul[ul])
			<< std::endl;
	}

	(void) ptmap->OsPrint(oss);

#endif	// GPOS_DEBUG

	GPOS_TRACE(str.GetBuffer());
	GPOS_DELETE(ptmap);

	return GPOS_OK;
}


//---------------------------------------------------------------------------
//	@function:
//		CTreeMapTest::EresUnittest_Unrank
//
//	@doc:
//		Rehydrate all trees encoded in the map
//
//---------------------------------------------------------------------------
GPOS_RESULT
CTreeMapTest::EresUnittest_Unrank()
{
	CAutoMemoryPool amp;
	CMemoryPool *mp = amp.Pmp();

	TestMap *ptmap = PtmapLoad(mp);

	// debug print
	CWStringDynamic str(mp);
	COstreamString oss(&str);

	ULLONG ullCount = ptmap->UllCount();

	for (ULONG ulRank = 0; ulRank < ullCount; ulRank++)
	{
		oss << "=== tree rank: " << ulRank << " ===" << std::endl;
		BOOL fFlag = true;
		CNode *pnd = ptmap->PrUnrank(mp, &fFlag, ulRank);

		pnd->Release();
	}

	GPOS_TRACE(str.GetBuffer());
	GPOS_DELETE(ptmap);

	return GPOS_OK;
}


//---------------------------------------------------------------------------
//	@function:
//		CTreeMapTest::EresUnittest_Memo
//
//	@doc:
//		Test loading map from actual memo
//
//---------------------------------------------------------------------------
GPOS_RESULT
CTreeMapTest::EresUnittest_Memo()
{
	GPOS_SET_TRACE(EtraceDisablePrintMemoryLeak);

	CAutoMemoryPool amp;
	CMemoryPool *mp = amp.Pmp();

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

	CEngine *peng = nullptr;
	CExpression *pexpr = nullptr;
	CQueryContext *pqc = nullptr;
	CExpression *pexprPlan = nullptr;
	{
		// install opt context in TLS
		CAutoOptCtxt aoc(mp, &mda, nullptr, /* pceeval */
						 CTestUtils::GetCostModel(mp));

		CAutoTraceFlag atf(EopttraceEnumeratePlans, true);

		peng = GPOS_NEW(mp) CEngine(mp);

		// generate join expression
		pexpr = CTestUtils::PexprLogicalJoin<CLogicalInnerJoin>(mp);

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

		// Initialize engine
		peng->Init(pqc, nullptr /*search_stage_array*/);

		// optimize query
		peng->Optimize();

		// extract plan
		pexprPlan = peng->PexprExtractPlan();
		GPOS_ASSERT(nullptr != pexprPlan);

		peng->Trace();
		{
			CAutoTrace at(mp);
			ULLONG ullCount = peng->Pmemotmap()->UllCount();
#ifdef GPOS_DEBUG
			// test resetting map and re-creating it
			peng->ResetTreeMap();
			ULLONG ullCount2 = peng->Pmemotmap()->UllCount();
			GPOS_ASSERT(ullCount == ullCount2);
#endif	// GPOS_DEBUG

			for (ULONG ulRank = 0; ulRank < ullCount; ulRank++)
			{
				CDrvdPropCtxtPlan *pdpctxtplan =
					GPOS_NEW(mp) CDrvdPropCtxtPlan(mp, false /*fUpdateCTEMap*/);
				CExpression *pexprAlt = nullptr;
				GPOS_TRY
				{
					pexprAlt =
						peng->Pmemotmap()->PrUnrank(mp, pdpctxtplan, ulRank);
					at.Os() << std::endl
							<< "ALTERNATIVE [" << ulRank << "]:" << std::endl
							<< *pexprAlt << std::endl;
				}
				GPOS_CATCH_EX(ex)
				{
					if (!GPOS_MATCH_EX(
							ex, gpopt::ExmaGPOPT,
							gpopt::ExmiUnsatisfiedRequiredProperties))
					{
						GPOS_RETHROW(ex);
					}
					IErrorContext *perrctxt = CTask::Self()->GetErrCtxt();
					at.Os() << perrctxt->GetErrorMsg() << std::endl;
					GPOS_RESET_EX;
				}
				GPOS_CATCH_END;
				CRefCount::SafeRelease(pexprAlt);
				CRefCount::SafeRelease(pdpctxtplan);
			}
		}
	}

	// clean up
	CRefCount::SafeRelease(pexprPlan);
	GPOS_DELETE(pqc);
	CRefCount::SafeRelease(pexpr);
	GPOS_DELETE(peng);

	return GPOS_OK;
}


#ifdef GPOS_DEBUG
//---------------------------------------------------------------------------
//	@function:
//		CTreeMapTest::EresUnittest_Cycle
//
//	@doc:
//		Introduce cycle in graph; counting must assert
//
//---------------------------------------------------------------------------
GPOS_RESULT
CTreeMapTest::EresUnittest_Cycle()
{
	CAutoMemoryPool amp;
	CMemoryPool *mp = amp.Pmp();

	TestMap *ptmap = GPOS_NEW(mp) TestMap(mp, &Pnd);

	CAutoP<TestMap> a_ptmap;
	a_ptmap = ptmap;

	// build cycle
	ptmap->Insert(&rgul[0], 0, &rgul[1]);
	ptmap->Insert(&rgul[1], 0, &rgul[2]);
	ptmap->Insert(&rgul[2], 0, &rgul[1]);

	(void) ptmap->UllCount();

	return GPOS_FAILED;
}

#endif	// GPOS_FAILED

// EOF

相关信息

greenplumn 源码目录

相关文章

greenplumn COptimizationJobsTest 源码

greenplumn CSearchStrategyTest 源码

0  赞