コード例 #1
0
ファイル: CLogicalTVF.cpp プロジェクト: MoZhonghua/gporca
//---------------------------------------------------------------------------
//	@function:
//		CLogicalTVF::CLogicalTVF
//
//	@doc:
//		Ctor
//
//---------------------------------------------------------------------------
CLogicalTVF::CLogicalTVF
	(
	IMemoryPool *pmp,
	IMDId *pmdidFunc,
	IMDId *pmdidRetType,
	CWStringConst *pstr,
	DrgPcoldesc *pdrgpcoldesc,
	DrgPcr *pdrgpcrOutput
	)
	:
	CLogical(pmp),
	m_pmdidFunc(pmdidFunc),
	m_pmdidRetType(pmdidRetType),
	m_pstr(pstr),
	m_pdrgpcoldesc(pdrgpcoldesc),
	m_pdrgpcrOutput(pdrgpcrOutput)
{
	GPOS_ASSERT(pmdidFunc->FValid());
	GPOS_ASSERT(pmdidRetType->FValid());
	GPOS_ASSERT(NULL != pstr);
	GPOS_ASSERT(NULL != pdrgpcoldesc);
	GPOS_ASSERT(NULL != pdrgpcrOutput);

	CMDAccessor *pmda = COptCtxt::PoctxtFromTLS()->Pmda();
	const IMDFunction *pmdfunc = pmda->Pmdfunc(m_pmdidFunc);

	m_efs = pmdfunc->EfsStability();
	m_efda = pmdfunc->EfdaDataAccess();
	m_fReturnsSet = pmdfunc->FReturnsSet();
}
コード例 #2
0
ファイル: CScalarAggFunc.cpp プロジェクト: MoZhonghua/gporca
//---------------------------------------------------------------------------
//	@function:
//		CScalarAggFunc::PmdidLookupReturnType
//
//	@doc:
//		Lookup mdid of return type for given Agg function
//
//---------------------------------------------------------------------------
IMDId *
CScalarAggFunc::PmdidLookupReturnType
	(
	IMDId *pmdidAggFunc,
	BOOL fGlobal,
	CMDAccessor *pmdaInput
	)
{
	GPOS_ASSERT(NULL != pmdidAggFunc);
	CMDAccessor *pmda = pmdaInput;

	if (NULL == pmda)
	{
		pmda = COptCtxt::PoctxtFromTLS()->Pmda();
	}
	GPOS_ASSERT(NULL != pmda);

	// get aggregate function return type from the MD cache
	const IMDAggregate *pmdagg = pmda->Pmdagg(pmdidAggFunc);
	if (fGlobal)
	{
		return pmdagg->PmdidTypeResult();
	}

	return pmdagg->PmdidTypeIntermediate();
}
コード例 #3
0
ファイル: CLogicalTVF.cpp プロジェクト: MoZhonghua/gporca
//---------------------------------------------------------------------------
//	@function:
//		CLogicalTVF::CLogicalTVF
//
//	@doc:
//		Ctor
//
//---------------------------------------------------------------------------
CLogicalTVF::CLogicalTVF
	(
	IMemoryPool *pmp,
	IMDId *pmdidFunc,
	IMDId *pmdidRetType,
	CWStringConst *pstr,
	DrgPcoldesc *pdrgpcoldesc
	)
	:
	CLogical(pmp),
	m_pmdidFunc(pmdidFunc),
	m_pmdidRetType(pmdidRetType),
	m_pstr(pstr),
	m_pdrgpcoldesc(pdrgpcoldesc),
	m_pdrgpcrOutput(NULL)
{
	GPOS_ASSERT(pmdidFunc->FValid());
	GPOS_ASSERT(pmdidRetType->FValid());
	GPOS_ASSERT(NULL != pstr);
	GPOS_ASSERT(NULL != pdrgpcoldesc);

	// generate a default column set for the list of column descriptors
	m_pdrgpcrOutput = PdrgpcrCreateMapping(pmp, pdrgpcoldesc, UlOpId());

	CMDAccessor *pmda = COptCtxt::PoctxtFromTLS()->Pmda();
	const IMDFunction *pmdfunc = pmda->Pmdfunc(m_pmdidFunc);

	m_efs = pmdfunc->EfsStability();
	m_efda = pmdfunc->EfdaDataAccess();
	m_fReturnsSet = pmdfunc->FReturnsSet();
}
コード例 #4
0
ファイル: CPhysicalTVF.cpp プロジェクト: MoZhonghua/gporca
//---------------------------------------------------------------------------
//	@function:
//		CPhysicalTVF::CPhysicalTVF
//
//	@doc:
//		Ctor
//
//---------------------------------------------------------------------------
CPhysicalTVF::CPhysicalTVF
	(
	IMemoryPool *pmp,
	IMDId *pmdidFunc,
	IMDId *pmdidRetType,
	CWStringConst *pstr,
	DrgPcoldesc *pdrgpcoldesc,
	CColRefSet *pcrsOutput
	)
	:
	CPhysical(pmp),
	m_pmdidFunc(pmdidFunc),
	m_pmdidRetType(pmdidRetType),
	m_pstr(pstr),
	m_pdrgpcoldesc(pdrgpcoldesc),
	m_pcrsOutput(pcrsOutput)
{
	GPOS_ASSERT(m_pmdidFunc->FValid());
	GPOS_ASSERT(m_pmdidRetType->FValid());
	GPOS_ASSERT(NULL != m_pstr);
	GPOS_ASSERT(NULL != m_pdrgpcoldesc);
	GPOS_ASSERT(NULL != m_pcrsOutput);

	CMDAccessor *pmda = COptCtxt::PoctxtFromTLS()->Pmda();
	m_pmdfunc = pmda->Pmdfunc(m_pmdidFunc);
}
コード例 #5
0
ファイル: CScalarOp.cpp プロジェクト: MoZhonghua/gporca
//---------------------------------------------------------------------------
//	@function:
//		CScalarOp::PmdidType
//
//	@doc:
//		Expression type
//
//---------------------------------------------------------------------------
IMDId *
CScalarOp::PmdidType() const
{
	if (NULL != m_pmdidReturnType)
	{
		return m_pmdidReturnType;
	}
	
	CMDAccessor *pmda = COptCtxt::PoctxtFromTLS()->Pmda();
	return pmda->Pmdscop(m_pmdidOp)->PmdidTypeResult();
}
コード例 #6
0
ファイル: CStatsPredUtils.cpp プロジェクト: d/gporca
//---------------------------------------------------------------------------
//	@function:
//		CStatsPredUtils::Estatscmpt
//
//	@doc:
//		For the purpose of statistics computation, what is the comparison
//		type of an operator. Note that this has different, looser semantics
//		than CUtils::Ecmpt
//
//---------------------------------------------------------------------------
CStatsPred::EStatsCmpType
CStatsPredUtils::Estatscmpt
	(
	IMDId *pmdid
	)
{
	CMDAccessor *pmda = COptCtxt::PoctxtFromTLS()->Pmda();
	const IMDScalarOp *pmdscop = pmda->Pmdscop(pmdid);

	// Simply go by operator name.
	// If the name of the operator is "<", then it is a LessThan etc.
	const CWStringConst *pstrOpName = pmdscop->Mdname().Pstr();

	return Estatscmpt(pstrOpName);
}
コード例 #7
0
ファイル: CPhysicalScan.cpp プロジェクト: HanumathRao/gporca
//---------------------------------------------------------------------------
//	@function:
//		CPhysicalScan::ComputeTableStats
//
//	@doc:
//		Compute stats of underlying table
//
//---------------------------------------------------------------------------
void
CPhysicalScan::ComputeTableStats
	(
	IMemoryPool *pmp
	)
{
	GPOS_ASSERT(NULL == m_pstatsBaseTable);

	CColRefSet *pcrsHist = GPOS_NEW(pmp) CColRefSet(pmp, m_pdrgpcrOutput);
	CColRefSet *pcrsWidth = GPOS_NEW(pmp) CColRefSet(pmp);

	CMDAccessor *pmda = COptCtxt::PoctxtFromTLS()->Pmda();
	m_pstatsBaseTable = pmda->Pstats(pmp, m_ptabdesc->Pmdid(), pcrsHist, pcrsWidth);
	GPOS_ASSERT(NULL != m_pstatsBaseTable);

	pcrsHist->Release();
	pcrsWidth->Release();
}
コード例 #8
0
ファイル: CLogical.cpp プロジェクト: HanumathRao/gporca
//---------------------------------------------------------------------------
//	@function:
//		CLogical::PstatsBaseTable
//
//	@doc:
//		Helper for deriving statistics on a base table
//
//---------------------------------------------------------------------------
IStatistics *
CLogical::PstatsBaseTable
	(
	IMemoryPool *pmp,
	CExpressionHandle &exprhdl,
	CTableDescriptor *ptabdesc,
	CColRefSet *pcrsHistExtra   // additional columns required for stats, not required by parent
	)
{
	CReqdPropRelational *prprel = CReqdPropRelational::Prprel(exprhdl.Prp());
	CColRefSet *pcrsHist = GPOS_NEW(pmp) CColRefSet(pmp);
	pcrsHist->Include(prprel->PcrsStat());
	if (NULL != pcrsHistExtra)
	{
		pcrsHist->Include(pcrsHistExtra);
	}

	CDrvdPropRelational *pdprel = exprhdl.Pdprel();
	CColRefSet *pcrsOutput = pdprel->PcrsOutput();
	CColRefSet *pcrsWidth = GPOS_NEW(pmp) CColRefSet(pmp);
	pcrsWidth->Include(pcrsOutput);
	pcrsWidth->Exclude(pcrsHist);

	const COptCtxt *poctxt = COptCtxt::PoctxtFromTLS();
	CMDAccessor *pmda = poctxt->Pmda();
	CStatisticsConfig *pstatsconf = poctxt->Poconf()->Pstatsconf();

	IStatistics *pstats = pmda->Pstats
								(
								pmp,
								ptabdesc->Pmdid(),
								pcrsHist,
								pcrsWidth,
								pstatsconf
								);

	// clean up
	pcrsWidth->Release();
	pcrsHist->Release();

	return pstats;
}
コード例 #9
0
ファイル: CLogical.cpp プロジェクト: margiex/gporca
//---------------------------------------------------------------------------
//	@function:
//		CLogical::PstatsBaseTable
//
//	@doc:
//		Helper for deriving statistics on a base table
//
//---------------------------------------------------------------------------
IStatistics *
CLogical::PstatsBaseTable
	(
	IMemoryPool *pmp,
	CExpressionHandle &exprhdl,
	CTableDescriptor *ptabdesc,
	CColRefSet *pcrsStatExtra   // additional columns required for stats, not required by parent
	)
{
	// extract colids and attribute for which detailed stats are necessary
	CReqdPropRelational *prprel = CReqdPropRelational::Prprel(exprhdl.Prp());
	CColRefSet *pcrsStat = GPOS_NEW(pmp) CColRefSet(pmp);
	pcrsStat->Include(prprel->PcrsStat());
	if (NULL != pcrsStatExtra)
	{
		pcrsStat->Include(pcrsStatExtra);
	}

	DrgPul *pdrgpulHistColIds = GPOS_NEW(pmp) DrgPul(pmp);
	DrgPul *pdrgpulHistPos = GPOS_NEW(pmp) DrgPul(pmp);
	CUtils::ExtractColIdsAttno(pmp, ptabdesc, pcrsStat, pdrgpulHistColIds, pdrgpulHistPos);

	// extract colids and attribute for which widths are necessary
	CDrvdPropRelational *pdprel = exprhdl.Pdprel();
	CColRefSet *pcrsWidth = pdprel->PcrsOutput();
	DrgPul *pdrgpulWidthColIds = GPOS_NEW(pmp) DrgPul(pmp);
	DrgPul *pdrgpulWidthPos = GPOS_NEW(pmp) DrgPul(pmp);
	CUtils::ExtractColIdsAttno(pmp, ptabdesc, pcrsWidth, pdrgpulWidthColIds, pdrgpulWidthPos);

	CMDAccessor *pmda = COptCtxt::PoctxtFromTLS()->Pmda();
	IStatistics *pstats = pmda->Pstats(pmp, ptabdesc->Pmdid(), pdrgpulHistPos, pdrgpulHistColIds, pdrgpulWidthPos, pdrgpulWidthColIds);

	if (!GPOS_FTRACE(EopttraceDonotCollectMissingStatsCols) && !pstats->FEmpty())
	{
		CStatisticsUtils::RecordMissingStatisticsColumns(pmp, ptabdesc, pcrsStat, pstats);
	}

	pcrsStat->Release();

	return pstats;
}
コード例 #10
0
ファイル: CPhysicalJoin.cpp プロジェクト: d/gporca
//---------------------------------------------------------------------------
//	@function:
//		CPhysicalJoin::FHashJoinCompatible
//
//	@doc:
//		Are the given predicate parts hash join compatible?
//		predicate parts are obtained by splitting equality into outer
//		and inner expressions
//
//---------------------------------------------------------------------------
BOOL
CPhysicalJoin::FHashJoinCompatible
	(
	CExpression *pexprOuter,	// outer child of the join
	CExpression* pexprInner,	// inner child of the join
	CExpression *pexprPredOuter,// outer part of join predicate
	CExpression *pexprPredInner // inner part of join predicate
	)
{
	GPOS_ASSERT(NULL != pexprOuter);
	GPOS_ASSERT(NULL != pexprInner);
	GPOS_ASSERT(NULL != pexprPredOuter);
	GPOS_ASSERT(NULL != pexprPredInner);

	IMDId *pmdidTypeOuter = CScalar::PopConvert(pexprPredOuter->Pop())->PmdidType();
	IMDId *pmdidTypeInner = CScalar::PopConvert(pexprPredInner->Pop())->PmdidType();

	CColRefSet *pcrsUsedPredOuter = CDrvdPropScalar::Pdpscalar(pexprPredOuter->PdpDerive())->PcrsUsed();
	CColRefSet *pcrsUsedPredInner = CDrvdPropScalar::Pdpscalar(pexprPredInner->PdpDerive())->PcrsUsed();

	CColRefSet *pcrsOuter = CDrvdPropRelational::Pdprel(pexprOuter->Pdp(CDrvdProp::EptRelational))->PcrsOutput();
	CColRefSet *pcrsInner = CDrvdPropRelational::Pdprel(pexprInner->Pdp(CDrvdProp::EptRelational))->PcrsOutput();

	// make sure that each predicate child uses columns from a different join child
	// in order to reject predicates of the form 'X Join Y on f(X.a, Y.b) = 5'
	BOOL fPredOuterUsesJoinOuterChild = (0 < pcrsUsedPredOuter->CElements()) && pcrsOuter->FSubset(pcrsUsedPredOuter);
	BOOL fPredOuterUsesJoinInnerChild = (0 < pcrsUsedPredOuter->CElements()) && pcrsInner->FSubset(pcrsUsedPredOuter);
	BOOL fPredInnerUsesJoinOuterChild = (0 < pcrsUsedPredInner->CElements()) && pcrsOuter->FSubset(pcrsUsedPredInner);
	BOOL fPredInnerUsesJoinInnerChild = (0 < pcrsUsedPredInner->CElements()) && pcrsInner->FSubset(pcrsUsedPredInner);

	BOOL fHashJoinCompatiblePred =
		(fPredOuterUsesJoinOuterChild && fPredInnerUsesJoinInnerChild) ||
		(fPredOuterUsesJoinInnerChild && fPredInnerUsesJoinOuterChild);

	CMDAccessor *pmda = COptCtxt::PoctxtFromTLS()->Pmda();

	return fHashJoinCompatiblePred &&
					pmda->Pmdtype(pmdidTypeOuter)->FHashable() &&
					pmda->Pmdtype(pmdidTypeInner)->FHashable();
}
コード例 #11
0
ファイル: CScalarCast.cpp プロジェクト: d/gporca
//---------------------------------------------------------------------------
//	@function:
//		CScalarCast::CScalarCast
//
//	@doc:
//		Ctor
//
//---------------------------------------------------------------------------
CScalarCast::CScalarCast
	(
	IMemoryPool *pmp,
	IMDId *pmdidReturnType,
	IMDId *pmdidFunc,
	BOOL fBinaryCoercible
	)
	:
	CScalar(pmp),
	m_pmdidReturnType(pmdidReturnType),
	m_pmdidFunc(pmdidFunc),
	m_fBinaryCoercible(fBinaryCoercible),
	m_fReturnsNullOnNullInput(false),
	m_fBoolReturnType(false)
{
	if (NULL != m_pmdidFunc && m_pmdidFunc->FValid())
	{
		CMDAccessor *pmda = COptCtxt::PoctxtFromTLS()->Pmda();
		const IMDFunction *pmdfunc = pmda->Pmdfunc(m_pmdidFunc);

		m_fReturnsNullOnNullInput = pmdfunc->FStrict();
		m_fBoolReturnType = CMDAccessorUtils::FBoolType(pmda, m_pmdidReturnType);
	}
}
コード例 #12
0
ファイル: CScalarWindowFunc.cpp プロジェクト: d/gporca
//---------------------------------------------------------------------------
//	@function:
//		CScalarWindowFunc::CScalarWindowFunc
//
//	@doc:
//		Ctor
//
//---------------------------------------------------------------------------
CScalarWindowFunc::CScalarWindowFunc
	(
	IMemoryPool *pmp,
	IMDId *pmdidFunc,
	IMDId *pmdidRetType,
	const CWStringConst *pstrFunc,
	EWinStage ewinstage,
	BOOL fDistinct
	)
	:
	CScalarFunc(pmp),
	m_ewinstage(ewinstage),
	m_fDistinct(fDistinct),
	m_fAgg(false)
{
	GPOS_ASSERT(pmdidFunc->FValid());
	GPOS_ASSERT(pmdidRetType->FValid());
	m_pmdidFunc = pmdidFunc;
	m_pmdidRetType = pmdidRetType;
	m_pstrFunc = pstrFunc;

	CMDAccessor *pmda = COptCtxt::PoctxtFromTLS()->Pmda();
	m_fAgg = pmda->FAggWindowFunc(m_pmdidFunc);
	if (!m_fAgg)
	{
		const IMDFunction *pmdfunc = pmda->Pmdfunc(m_pmdidFunc);
		m_efs = pmdfunc->EfsStability();
		m_efda = pmdfunc->EfdaDataAccess();
	}
	else
	{
 	 	// TODO: , Aug 15, 2012; pull out properties of aggregate functions
		m_efs = IMDFunction::EfsImmutable;
		m_efda = IMDFunction::EfdaNoSQL;
	}
}
コード例 #13
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();
}
コード例 #14
0
ファイル: CLogical.cpp プロジェクト: HanumathRao/gporca
//---------------------------------------------------------------------------
//	@function:
//		CLogical::PpcDeriveConstraintFromTable
//
//	@doc:
//		Derive constraint property from a table/index get
//
//---------------------------------------------------------------------------
CPropConstraint *
CLogical::PpcDeriveConstraintFromTable
	(
	IMemoryPool *pmp,
	const CTableDescriptor *ptabdesc,
	const DrgPcr *pdrgpcrOutput
	)
{
	DrgPcrs *pdrgpcrs = GPOS_NEW(pmp) DrgPcrs(pmp);

	DrgPcnstr *pdrgpcnstr = GPOS_NEW(pmp) DrgPcnstr(pmp);

	const DrgPcoldesc *pdrgpcoldesc = ptabdesc->Pdrgpcoldesc();
	const ULONG ulCols = pdrgpcoldesc->UlLength();

	DrgPcr *pdrgpcrNonSystem = GPOS_NEW(pmp) DrgPcr(pmp);

	for (ULONG ul = 0; ul < ulCols; ul++)
	{
		CColumnDescriptor *pcoldesc = (*pdrgpcoldesc)[ul];
		CColRef *pcr = (*pdrgpcrOutput)[ul];
		// we are only interested in non-system columns that are defined as
		// being NOT NULL

		if (pcoldesc->FSystemColumn())
		{
			continue;
		}

		pdrgpcrNonSystem->Append(pcr);

		if (pcoldesc->FNullable())
		{
			continue;
		}

		// add a "not null" constraint and an equivalence class
		CConstraint * pcnstr = CConstraintInterval::PciUnbounded(pmp, pcr, false /*fIncludesNull*/);

		if (pcnstr == NULL)
		{
			continue;
		}
		pdrgpcnstr->Append(pcnstr);

		CColRefSet *pcrsEquiv = GPOS_NEW(pmp) CColRefSet(pmp);
		pcrsEquiv->Include(pcr);
		pdrgpcrs->Append(pcrsEquiv);
	}

	CMDAccessor *pmda = COptCtxt::PoctxtFromTLS()->Pmda();
	const IMDRelation *pmdrel = pmda->Pmdrel(ptabdesc->Pmdid());

	const ULONG ulCheckConstraint = pmdrel->UlCheckConstraints();
	for (ULONG ul = 0; ul < ulCheckConstraint; ul++)
	{
		IMDId *pmdidCheckConstraint = pmdrel->PmdidCheckConstraint(ul);

		const IMDCheckConstraint *pmdCheckConstraint = pmda->Pmdcheckconstraint(pmdidCheckConstraint);

		// extract the check constraint expression
		CExpression *pexprCheckConstraint = pmdCheckConstraint->Pexpr(pmp, pmda, pdrgpcrNonSystem);
		GPOS_ASSERT(NULL != pexprCheckConstraint);
		GPOS_ASSERT(CUtils::FPredicate(pexprCheckConstraint));

		DrgPcrs *pdrgpcrsChild = NULL;
		CConstraint *pcnstr = CConstraint::PcnstrFromScalarExpr(pmp, pexprCheckConstraint, &pdrgpcrsChild);
		if (NULL != pcnstr)
		{
			pdrgpcnstr->Append(pcnstr);

			// merge with the equivalence classes we have so far
			DrgPcrs *pdrgpcrsMerged = CUtils::PdrgpcrsMergeEquivClasses(pmp, pdrgpcrs, pdrgpcrsChild);
			pdrgpcrs->Release();
			pdrgpcrs = pdrgpcrsMerged;
		}
		CRefCount::SafeRelease(pdrgpcrsChild);
		pexprCheckConstraint->Release();
	}

	pdrgpcrNonSystem->Release();

	return GPOS_NEW(pmp) CPropConstraint(pmp, pdrgpcrs, CConstraint::PcnstrConjunction(pmp, pdrgpcnstr));
}