Пример #1
0
//---------------------------------------------------------------------------
//	@function:
//		CConstraintConjunction::Pcnstr
//
//	@doc:
//		Return constraint on a given column
//
//---------------------------------------------------------------------------
CConstraint *
CConstraintConjunction::Pcnstr
	(
	IMemoryPool *mp,
	const CColRef *colref
	)
{
	// all children referencing given column
	CConstraintArray *pdrgpcnstrCol = m_phmcolconstr->Find(colref);
	if (NULL == pdrgpcnstrCol)
	{
		return NULL;
	}

	CConstraintArray *pdrgpcnstr = GPOS_NEW(mp) CConstraintArray(mp);

	const ULONG length = pdrgpcnstrCol->Size();
	for (ULONG ul = 0; ul < length; ul++)
	{
		// the part of the child that references this column
		CConstraint *pcnstrCol = (*pdrgpcnstrCol)[ul]->Pcnstr(mp, colref);
		if (NULL == pcnstrCol || pcnstrCol->IsConstraintUnbounded())
		{
			CRefCount::SafeRelease(pcnstrCol);
			continue;
		}
		pdrgpcnstr->Append(pcnstrCol);
	}

	return CConstraint::PcnstrConjunction(mp, pdrgpcnstr);
}
Пример #2
0
//---------------------------------------------------------------------------
//	@function:
//		CPartConstraint::FSubsume
//
//	@doc:
//		Does constraint subsume given one
//
//---------------------------------------------------------------------------
BOOL
CPartConstraint::FSubsume
	(
	const CPartConstraint *ppartcnstr
	)
	const
{
	GPOS_ASSERT(NULL != ppartcnstr);
	GPOS_ASSERT(!m_fUninterpreted && "Calling FSubsume on uninterpreted partition constraint");

	if (IsConstraintUnbounded())
	{
		return true;
	}

	if (ppartcnstr->IsConstraintUnbounded())
	{
		return false;
	}

	BOOL fSubsumeLevel = true;
	for (ULONG ul = 0; ul < m_num_of_part_levels && fSubsumeLevel; ul++)
	{
		CConstraint *pcnstrCurrent = Pcnstr(ul);
		CConstraint *pcnstrOther = ppartcnstr->Pcnstr(ul);
		GPOS_ASSERT(NULL != pcnstrCurrent);
		GPOS_ASSERT(NULL != pcnstrOther);

		fSubsumeLevel = pcnstrCurrent->Contains(pcnstrOther) &&
						(IsDefaultPartition(ul) || !ppartcnstr->IsDefaultPartition(ul));
	}

	return fSubsumeLevel;
}
// mapping between columns and single column constraints in array of constraints
static
HMColConstr *
PhmcolconstrSingleColConstr
	(
		IMemoryPool *pmp,
		DrgPcnstr *drgPcnstr
	)
{
	CAutoRef<DrgPcnstr> arpdrgpcnstr(drgPcnstr);
	HMColConstr *phmcolconstr = GPOS_NEW(pmp) HMColConstr(pmp);

	const ULONG ulLen = arpdrgpcnstr->UlLength();

	for (ULONG ul = 0; ul < ulLen; ul++)
	{
		CConstraint *pcnstrChild = (*arpdrgpcnstr)[ul];
		CColRefSet *pcrs = pcnstrChild->PcrsUsed();

		if (1 == pcrs->CElements())
		{
			CColRef *pcr = pcrs->PcrFirst();
			DrgPcnstr *pcnstrMapped = phmcolconstr->PtLookup(pcr);
			if (NULL == pcnstrMapped)
			{
				pcnstrMapped = GPOS_NEW(pmp) DrgPcnstr(pmp);
				phmcolconstr->FInsert(pcr, pcnstrMapped);
			}
			pcnstrChild->AddRef();
			pcnstrMapped->Append(pcnstrChild);
		}
	}

	return phmcolconstr;
}
Пример #4
0
//---------------------------------------------------------------------------
//	@function:
//		CPartConstraint::FEqualConstrMaps
//
//	@doc:
//		Check if two constaint maps have the same constraints
//
//---------------------------------------------------------------------------
BOOL
CPartConstraint::FEqualConstrMaps
	(
	UlongToConstraintMap *phmulcnstrFst,
	UlongToConstraintMap *phmulcnstrSnd,
	ULONG ulLevels
	)
{
	if (phmulcnstrFst->Size() != phmulcnstrSnd->Size())
	{
		return false;
	}

	for (ULONG ul = 0; ul < ulLevels; ul++)
	{
		CConstraint *pcnstrFst = phmulcnstrFst->Find(&ul);
		CConstraint *pcnstrSnd = phmulcnstrSnd->Find(&ul);

		if ((NULL == pcnstrFst || NULL == pcnstrSnd) && pcnstrFst != pcnstrSnd)
		{
			return false;
		}

		if (NULL != pcnstrFst && !pcnstrFst->Equals(pcnstrSnd))
		{
			return false;
		}
	}

	return true;
}
Пример #5
0
//---------------------------------------------------------------------------
//	@function:
//		CConstraint::PdrgpcnstrOnColumn
//
//	@doc:
//		Return a subset of the given constraints which reference the
//		given column
//
//---------------------------------------------------------------------------
DrgPcnstr *
CConstraint::PdrgpcnstrOnColumn
(
    IMemoryPool *pmp,
    DrgPcnstr *pdrgpcnstr,
    CColRef *pcr,
    BOOL fExclusive		// returned constraints must reference ONLY the given col
)
{
    DrgPcnstr *pdrgpcnstrSubset = GPOS_NEW(pmp) DrgPcnstr(pmp);

    const ULONG ulLen = pdrgpcnstr->UlLength();

    for (ULONG ul = 0; ul < ulLen; ul++)
    {
        CConstraint *pcnstr = (*pdrgpcnstr)[ul];
        CColRefSet *pcrs = pcnstr->PcrsUsed();

        // if the fExclusive flag is true, then pcr must be the only column
        if (pcrs->FMember(pcr) && (!fExclusive || 1 == pcrs->CElements()))
        {
            pcnstr->AddRef();
            pdrgpcnstrSubset->Append(pcnstr);
        }
    }

    return pdrgpcnstrSubset;
}
Пример #6
0
//---------------------------------------------------------------------------
//	@function:
//		CConstraintConjunction::CConstraintConjunction
//
//	@doc:
//		Ctor
//
//---------------------------------------------------------------------------
CConstraintConjunction::CConstraintConjunction
	(
	IMemoryPool *mp,
	CConstraintArray *pdrgpcnstr
	)
	:
	CConstraint(mp),
	m_pdrgpcnstr(NULL)
{
	GPOS_ASSERT(NULL != pdrgpcnstr);
	m_pdrgpcnstr = PdrgpcnstrFlatten(mp, pdrgpcnstr, EctConjunction);

	const ULONG length = m_pdrgpcnstr->Size();
	GPOS_ASSERT(0 < length);

	m_pcrsUsed = GPOS_NEW(mp) CColRefSet(mp);

	for (ULONG ul = 0; ul < length; ul++)
	{
		CConstraint *pcnstr = (*m_pdrgpcnstr)[ul];
		m_pcrsUsed->Include(pcnstr->PcrsUsed());
	}

	m_phmcolconstr = Phmcolconstr(mp, m_pcrsUsed, m_pdrgpcnstr);
}
Пример #7
0
//---------------------------------------------------------------------------
//	@function:
//		CConstraintConjunction::Pcnstr
//
//	@doc:
//		Return constraint on a given column set
//
//---------------------------------------------------------------------------
CConstraint *
CConstraintConjunction::Pcnstr
	(
	IMemoryPool *mp,
	CColRefSet *pcrs
	)
{
	const ULONG length = m_pdrgpcnstr->Size();

	CConstraintArray *pdrgpcnstr = GPOS_NEW(mp) CConstraintArray(mp);

	for (ULONG ul = 0; ul < length; ul++)
	{
		CConstraint *pcnstr = (*m_pdrgpcnstr)[ul];
		if (pcnstr->PcrsUsed()->IsDisjoint(pcrs))
		{
			continue;
		}

		// the part of the child that references these columns
		CConstraint *pcnstrCol = pcnstr->Pcnstr(mp, pcrs);
		if (NULL != pcnstrCol)
		{
			pdrgpcnstr->Append(pcnstrCol);
		}
	}

	return CConstraint::PcnstrConjunction(mp, pdrgpcnstr);
}
Пример #8
0
//---------------------------------------------------------------------------
//	@function:
//		CPartConstraint::FDisjunctionPossible
//
//	@doc:
//		Check if it is possible to produce a disjunction of the two given part
//		constraints. This is possible if the first ulLevels-1 have the same
//		constraints and default flags for both part constraints
//
//---------------------------------------------------------------------------
BOOL
CPartConstraint::FDisjunctionPossible
	(
	CPartConstraint *ppartcnstrFst,
	CPartConstraint *ppartcnstrSnd
	)
{
	GPOS_ASSERT(NULL != ppartcnstrFst);
	GPOS_ASSERT(NULL != ppartcnstrSnd);
	GPOS_ASSERT(ppartcnstrFst->m_num_of_part_levels == ppartcnstrSnd->m_num_of_part_levels);

	const ULONG ulLevels = ppartcnstrFst->m_num_of_part_levels;
	BOOL fSuccess = true;

	for (ULONG ul = 0; fSuccess && ul < ulLevels - 1; ul++)
	{
		CConstraint *pcnstrFst = ppartcnstrFst->Pcnstr(ul);
		CConstraint *pcnstrSnd = ppartcnstrSnd->Pcnstr(ul);
		fSuccess = (NULL != pcnstrFst &&
					NULL != pcnstrSnd &&
					pcnstrFst->Equals(pcnstrSnd) &&
					ppartcnstrFst->IsDefaultPartition(ul) == ppartcnstrSnd->IsDefaultPartition(ul));
	}

	// last level constraints cannot be NULL as well
	fSuccess = (fSuccess &&
				NULL != ppartcnstrFst->Pcnstr(ulLevels - 1) &&
				NULL != ppartcnstrSnd->Pcnstr(ulLevels - 1));

	return fSuccess;
}
Пример #9
0
//---------------------------------------------------------------------------
//	@function:
//		CLogicalSetOp::PcnstrColumn
//
//	@doc:
//		Get constraint for a given output column from a given children
//
//---------------------------------------------------------------------------
CConstraint *
CLogicalSetOp::PcnstrColumn
	(
	IMemoryPool *pmp,
	CExpressionHandle &exprhdl,
	ULONG ulColIndex,
	ULONG ulChild
	)
	const
{
	GPOS_ASSERT(ulChild < exprhdl.UlArity());

	// constraint from child
	CConstraint *pcnstrChild = exprhdl.Pdprel(ulChild)->Ppc()->Pcnstr();
	if (NULL == pcnstrChild)
	{
		return NULL;
	}

	// part of constraint on the current input column
	CConstraint *pcnstrCol = pcnstrChild->Pcnstr(pmp, (*(*m_pdrgpdrgpcrInput)[ulChild])[ulColIndex]);
	if (NULL == pcnstrCol)
	{
		return NULL;
	}

	// make a copy of this constraint but for the output column instead
	CConstraint *pcnstrOutput = pcnstrCol->PcnstrRemapForColumn(pmp, (*m_pdrgpcrOutput)[ulColIndex]);
	pcnstrCol->Release();
	return pcnstrOutput;
}
Пример #10
0
//---------------------------------------------------------------------------
//	@function:
//		CPartConstraint::PpartcnstrRemaining
//
//	@doc:
//		Return what remains of the current part constraint after taking out
//		the given part constraint. Returns NULL is the difference cannot be
//		performed
//
//---------------------------------------------------------------------------
CPartConstraint *
CPartConstraint::PpartcnstrRemaining
	(
	IMemoryPool *mp,
	CPartConstraint *ppartcnstr
	)
{
	GPOS_ASSERT(!m_fUninterpreted && "Calling PpartcnstrRemaining on uninterpreted partition constraint");
	GPOS_ASSERT(NULL != ppartcnstr);

	if (m_num_of_part_levels != ppartcnstr->m_num_of_part_levels || !ppartcnstr->FCanNegate())
	{
		return NULL;
	}

	UlongToConstraintMap *phmulcnstr = GPOS_NEW(mp) UlongToConstraintMap(mp);
	CBitSet *pbsDefaultParts = GPOS_NEW(mp) CBitSet(mp);

	// constraint on first level
	CConstraint *pcnstrCurrent = Pcnstr(0 /*ulLevel*/);
	CConstraint *pcnstrOther = ppartcnstr->Pcnstr(0 /*ulLevel*/);

	CConstraint *pcnstrRemaining = PcnstrRemaining(mp, pcnstrCurrent, pcnstrOther);

#ifdef GPOS_DEBUG
	BOOL result =
#endif // GPOS_DEBUG
	phmulcnstr->Insert(GPOS_NEW(mp) ULONG(0), pcnstrRemaining);
	GPOS_ASSERT(result);

	if (IsDefaultPartition(0 /*ulLevel*/) && !ppartcnstr->IsDefaultPartition(0 /*ulLevel*/))
	{
		pbsDefaultParts->ExchangeSet(0 /*ulBit*/);
	}

	// copy the remaining constraints and default partition flags
	for (ULONG ul = 1; ul < m_num_of_part_levels; ul++)
	{
		CConstraint *pcnstrLevel = Pcnstr(ul);
		if (NULL != pcnstrLevel)
		{
			pcnstrLevel->AddRef();
#ifdef GPOS_DEBUG
			BOOL result =
#endif // GPOS_DEBUG
			phmulcnstr->Insert(GPOS_NEW(mp) ULONG(ul), pcnstrLevel);
			GPOS_ASSERT(result);
		}

		if (IsDefaultPartition(ul))
		{
			pbsDefaultParts->ExchangeSet(ul);
		}
	}

	m_pdrgpdrgpcr->AddRef();
	return GPOS_NEW(mp) CPartConstraint(mp, phmulcnstr, pbsDefaultParts, false /*is_unbounded*/, m_pdrgpdrgpcr);
}
Пример #11
0
//---------------------------------------------------------------------------
//	@function:
//		CConstraint::PcnstrConjDisj
//
//	@doc:
//		Create conjunction/disjunction from array of constraints
//
//---------------------------------------------------------------------------
CConstraint *
CConstraint::PcnstrConjDisj
(
    IMemoryPool *pmp,
    DrgPcnstr *pdrgpcnstr,
    BOOL fConj
)
{
    GPOS_ASSERT(NULL != pdrgpcnstr);

    CConstraint *pcnstr = NULL;

    const ULONG ulLen = pdrgpcnstr->UlLength();

    switch (ulLen)
    {
    case 0:
    {
        pdrgpcnstr->Release();
        break;
    }

    case 1:
    {
        pcnstr = (*pdrgpcnstr)[0];
        pcnstr->AddRef();
        pdrgpcnstr->Release();
        break;
    }

    default:
    {
        if (fConj)
        {
            pcnstr = GPOS_NEW(pmp) CConstraintConjunction(pmp, pdrgpcnstr);
        }
        else
        {
            pcnstr = GPOS_NEW(pmp) CConstraintDisjunction(pmp, pdrgpcnstr);
        }
    }
    }

    return pcnstr;
}
Пример #12
0
//---------------------------------------------------------------------------
//	@function:
//		CPartConstraint::FOverlapLevel
//
//	@doc:
//		Does the current constraint overlap with given one at the given level
//
//---------------------------------------------------------------------------
BOOL
CPartConstraint::FOverlapLevel
	(
	IMemoryPool *mp,
	const CPartConstraint *ppartcnstr,
	ULONG ulLevel
	)
	const
{
	GPOS_ASSERT(NULL != ppartcnstr);
	GPOS_ASSERT(!IsConstraintUnbounded());
	GPOS_ASSERT(!ppartcnstr->IsConstraintUnbounded());

	CConstraintArray *pdrgpcnstr = GPOS_NEW(mp) CConstraintArray(mp);
	CConstraint *pcnstrCurrent = Pcnstr(ulLevel);
	CConstraint *pcnstrOther = ppartcnstr->Pcnstr(ulLevel);
	GPOS_ASSERT(NULL != pcnstrCurrent);
	GPOS_ASSERT(NULL != pcnstrOther);

	pcnstrCurrent->AddRef();
	pcnstrOther->AddRef();
	pdrgpcnstr->Append(pcnstrCurrent);
	pdrgpcnstr->Append(pcnstrOther);

	CConstraint *pcnstrIntersect = CConstraint::PcnstrConjunction(mp, pdrgpcnstr);

	BOOL fOverlap = !pcnstrIntersect->FContradiction();
	pcnstrIntersect->Release();

	return fOverlap || (IsDefaultPartition(ulLevel) && ppartcnstr->IsDefaultPartition(ulLevel));
}
Пример #13
0
//---------------------------------------------------------------------------
//	@function:
//		CConstraintConjunction::PcnstrCopyWithRemappedColumns
//
//	@doc:
//		Return a copy of the constraint with remapped columns. If must_exist is
//		set to true, then every column reference in this constraint must be in
//		the hashmap in order to be replace. Otherwise, some columns may not be
//		in the mapping, and hence will not be replaced
//
//---------------------------------------------------------------------------
CConstraint *
CConstraintConjunction::PcnstrCopyWithRemappedColumns
	(
	IMemoryPool *mp,
	UlongToColRefMap *colref_mapping,
	BOOL must_exist
	)
{
	CConstraintArray *pdrgpcnstr = GPOS_NEW(mp) CConstraintArray(mp);
	const ULONG length = m_pdrgpcnstr->Size();
	for (ULONG ul = 0; ul < length; ul++)
	{
		CConstraint *pcnstr = (*m_pdrgpcnstr)[ul];
		CConstraint *pcnstrCopy = pcnstr->PcnstrCopyWithRemappedColumns(mp, colref_mapping, must_exist);
		pdrgpcnstr->Append(pcnstrCopy);
	}
	return GPOS_NEW(mp) CConstraintConjunction(mp, pdrgpcnstr);
}
Пример #14
0
void CSimuEntity::applyAllPositionConstraints(const double &current_tm, const double &dt)
{
	{//apply collision constraints, which has the lowest priority
		CCollisionConstraint *p = m_pCollisionConstraint;
		if (p && p->isEnabled() && (!p->isExpired(current_tm))){
			p->applyConstraint(this, current_tm, dt);
		}
	}

	//other constraints, user specified
	for (int i=0; i<CONSTRAINT_BUFF_LENGTH; i++){
		CConstraint *p = m_pConstraints[i];
		if (p){
			if (p->isEnabled() && (!p->isExpired(current_tm)))
				p->applyConstraint(this, current_tm, dt);
		}
	}
}
Пример #15
0
//---------------------------------------------------------------------------
//	@function:
//		CLogical::PpcDeriveConstraintFromTableWithPredicates
//
//	@doc:
//		Derive constraint property from a table/index get with predicates
//
//---------------------------------------------------------------------------
CPropConstraint *
CLogical::PpcDeriveConstraintFromTableWithPredicates
	(
	IMemoryPool *pmp,
	CExpressionHandle &exprhdl,
	const CTableDescriptor *ptabdesc,
	const DrgPcr *pdrgpcrOutput
	)
{
	DrgPcnstr *pdrgpcnstr = GPOS_NEW(pmp) DrgPcnstr(pmp);
	CPropConstraint *ppcTable = PpcDeriveConstraintFromTable(pmp, ptabdesc, pdrgpcrOutput);
	CConstraint *pcnstrTable = ppcTable->Pcnstr();
	if (NULL != pcnstrTable)
	{
		pcnstrTable->AddRef();
		pdrgpcnstr->Append(pcnstrTable);
	}
	DrgPcrs *pdrgpcrsEquivClassesTable = ppcTable->PdrgpcrsEquivClasses();

	CPropConstraint *ppcnstrCond = PpcDeriveConstraintFromPredicates(pmp, exprhdl);
	CConstraint *pcnstrCond = ppcnstrCond->Pcnstr();

	if (NULL != pcnstrCond)
	{
		pcnstrCond->AddRef();
		pdrgpcnstr->Append(pcnstrCond);
	}
	else if (NULL == pcnstrTable)
	{
		ppcTable->Release();
		pdrgpcnstr->Release();

		return ppcnstrCond;
	}

	DrgPcrs *pdrgpcrsCond = ppcnstrCond->PdrgpcrsEquivClasses();
	DrgPcrs *pdrgpcrs = CUtils::PdrgpcrsMergeEquivClasses(pmp, pdrgpcrsEquivClassesTable, pdrgpcrsCond);
	CPropConstraint *ppc = GPOS_NEW(pmp) CPropConstraint(pmp, pdrgpcrs, CConstraint::PcnstrConjunction(pmp, pdrgpcnstr));

	ppcnstrCond->Release();
	ppcTable->Release();

	return ppc;
}
Пример #16
0
//---------------------------------------------------------------------------
//	@function:
//		CPartConstraint::PcnstrBuildCombined
//
//	@doc:
//		Construct the combined constraint
//
//---------------------------------------------------------------------------
CConstraint *
CPartConstraint::PcnstrBuildCombined
	(
	IMemoryPool *mp
	)
{
	CConstraintArray *pdrgpcnstr = GPOS_NEW(mp) CConstraintArray(mp);
	for (ULONG ul = 0; ul < m_num_of_part_levels; ul++)
	{
		CConstraint *pcnstr = m_phmulcnstr->Find(&ul);
		if (NULL != pcnstr)
		{
			pcnstr->AddRef();
			pdrgpcnstr->Append(pcnstr);
		}
	}

	return CConstraint::PcnstrConjunction(mp, pdrgpcnstr);
}
Пример #17
0
//---------------------------------------------------------------------------
//	@function:
//		CPartConstraint::FCanNegate
//
//	@doc:
//		Check whether or not the current part constraint can be negated. A part
//		constraint can be negated only if it has constraints on the first level
//
//---------------------------------------------------------------------------
BOOL
CPartConstraint::FCanNegate() const
{
	// first level cannot be NULL
	if (NULL == Pcnstr(0))
	{
		return false;
	}

	// all levels after the first must be unconstrained
	for (ULONG ul = 1; ul < m_num_of_part_levels; ul++)
	{
		CConstraint *pcnstr = Pcnstr(ul);
		if (NULL == pcnstr || !pcnstr->IsConstraintUnbounded())
		{
			return false;
		}
	}

	return true;
}
Пример #18
0
void CSimuEntity::addConstraint(const CConstraint *pconstraint)
{
	int i, j;
	//find the right position using linear search
	const int nprior = pconstraint->getPrior();
	for (i=0; i<CONSTRAINT_BUFF_LENGTH-1; i++){
		CConstraint *p = m_pConstraints[i];	
		if (p){
			const int n1 = p->getPrior();
			if (n1>nprior) break;
		}
		else{
			m_pConstraints[i] = (CConstraint *)pconstraint;
			return;
		}
	}
	//insert and move 
	for (j=CONSTRAINT_BUFF_LENGTH-1; j>i; j--)
		m_pConstraints[j] = m_pConstraints[j-1];	
	m_pConstraints[i] = (CConstraint *)pconstraint;
}
Пример #19
0
DLL_DECL bool 
VerifyConstraint(const char *constraint)
{
	bool ret = true;
    if (!CManager::theInstance->HasConstraints())
		return ret;

	CDynConstraintSetList & setlist = CManager::theInstance->GetConstraintSets();

	POSITION sl_pos = setlist.GetHeadPosition();
	bool found=false;
	while (sl_pos && !found)
	{
		CDynConstraintSet * setlist_i = setlist.GetNext(sl_pos);
		CDynConstraintList& list = setlist_i->GetConstraints();
		POSITION pos1 = list.GetHeadPosition();
		while(pos1)
		{
			CDynConstraint *cur = list.GetNext(pos1);
			const CString& nm  = cur->GetName();

			if (nm==CString(constraint))
			{
				CConstraint *con = (CConstraint *)cur->GetCore();
				CString err_str, what;
				bool isvalid = con->Verify(err_str, what);
				if(!isvalid)
				{
					CCSetErrDialog cse_dialog;
					cse_dialog.AddError(NULL,*cur, *(cur->GetContext()), (LPCTSTR)err_str,  what);
				}
				found = true;
				break;
			}
		}
	}

	return ret;
}
Пример #20
0
//---------------------------------------------------------------------------
//	@function:
//		CConstraint::PdrgpcnstrFlatten
//
//	@doc:
//		Flatten an array of constraints to be used as children for a conjunction
//		or disjunction. If any of these children is of the same type then use
//		its children directly instead of having multiple levels of the same type
//
//---------------------------------------------------------------------------
DrgPcnstr *
CConstraint::PdrgpcnstrFlatten
(
    IMemoryPool *pmp,
    DrgPcnstr *pdrgpcnstr,
    EConstraintType ect
)
const
{
    DrgPcnstr *pdrgpcnstrNew = GPOS_NEW(pmp) DrgPcnstr(pmp);

    const ULONG ulLen = pdrgpcnstr->UlLength();
    for (ULONG ul = 0; ul < ulLen; ul++)
    {
        CConstraint *pcnstrChild = (*pdrgpcnstr)[ul];
        EConstraintType ectChild = pcnstrChild->Ect();

        if (EctConjunction == ectChild && EctConjunction == ect)
        {
            CConstraintConjunction *pcconj = (CConstraintConjunction *)pcnstrChild;
            CUtils::AddRefAppend<CConstraint, CleanupRelease>(pdrgpcnstrNew, pcconj->Pdrgpcnstr());
        }
        else if (EctDisjunction == ectChild && EctDisjunction == ect)
        {
            CConstraintDisjunction *pcdisj = (CConstraintDisjunction *)pcnstrChild;
            CUtils::AddRefAppend<CConstraint, CleanupRelease>(pdrgpcnstrNew, pcdisj->Pdrgpcnstr());
        }
        else
        {
            pcnstrChild->AddRef();
            pdrgpcnstrNew->Append(pcnstrChild);
        }
    }

    pdrgpcnstr->Release();
    return PdrgpcnstrDeduplicate(pmp, pdrgpcnstrNew, ect);
}
Пример #21
0
//---------------------------------------------------------------------------
//	@function:
//		CPartConstraint::PpartcnstrCopyWithRemappedColumns
//
//	@doc:
//		Return a copy of the part constraint with remapped columns
//
//---------------------------------------------------------------------------
CPartConstraint *
CPartConstraint::PpartcnstrCopyWithRemappedColumns
	(
	IMemoryPool *mp,
	UlongToColRefMap *colref_mapping,
	BOOL must_exist
	)
{
	if (m_fUninterpreted)
	{
		return GPOS_NEW(mp) CPartConstraint(true /*m_fUninterpreted*/);
	}

	UlongToConstraintMap *phmulcnstr = GPOS_NEW(mp) UlongToConstraintMap(mp);
	CColRef2dArray *pdrgpdrgpcr = GPOS_NEW(mp) CColRef2dArray(mp);

	for (ULONG ul = 0; ul < m_num_of_part_levels; ul++)
	{
		CColRefArray *colref_array = (*m_pdrgpdrgpcr)[ul];
		CColRefArray *pdrgpcrMapped = CUtils::PdrgpcrRemap(mp, colref_array, colref_mapping, must_exist);
		pdrgpdrgpcr->Append(pdrgpcrMapped);

		CConstraint *pcnstr = Pcnstr(ul);
		if (NULL != pcnstr)
		{
			CConstraint *pcnstrRemapped = pcnstr->PcnstrCopyWithRemappedColumns(mp, colref_mapping, must_exist);
#ifdef GPOS_DEBUG
			BOOL result =
#endif // GPOS_DEBUG
			phmulcnstr->Insert(GPOS_NEW(mp) ULONG(ul), pcnstrRemapped);
			GPOS_ASSERT(result);
		}
	}

	m_pbsDefaultParts->AddRef();
	return GPOS_NEW(mp) CPartConstraint(mp, phmulcnstr, m_pbsDefaultParts, m_is_unbounded, pdrgpdrgpcr);
}
Пример #22
0
//---------------------------------------------------------------------------
//	@function:
//		CPartConstraint::OsPrint
//
//	@doc:
//		Debug print
//
//---------------------------------------------------------------------------
IOstream &
CPartConstraint::OsPrint
	(
	IOstream &os
	)
	const
{
	os << "Part constraint: (";
	if (m_fUninterpreted)
	{
		os << "uninterpreted)";
		return os;
	}

	for (ULONG ul = 0; ul < m_num_of_part_levels; ul++)
	{
		if (ul > 0)
		{
			os << ", ";
		}
		CConstraint *pcnstr = Pcnstr(ul);
		if (NULL != pcnstr)
		{
			pcnstr->OsPrint(os);
		}
		else
		{
			os << "-";
		}
	}
	
	os << ", default partitions on levels: " << *m_pbsDefaultParts
		<< ", unbounded: " << m_is_unbounded;
	os << ")";
	return os;
}
Пример #23
0
//---------------------------------------------------------------------------
//	@function:
//		CConstraint::FContains
//
//	@doc:
//		Does the current constraint contain the given one?
//
//---------------------------------------------------------------------------
BOOL
CConstraint::FContains
(
    CConstraint *pcnstr
)
{
    if (FUnbounded())
    {
        return true;
    }

    if (NULL == pcnstr || pcnstr->FUnbounded())
    {
        return false;
    }

    if (this == pcnstr)
    {
        // a constraint always contains itself
        return true;
    }

    // check if we have computed this containment query before
    BOOL *pfContains = m_phmcontain->PtLookup(pcnstr);
    if (NULL != pfContains)
    {
        return *pfContains;
    }

    BOOL fContains = true;

    // for each column used by the current constraint, we have to make sure that
    // the constraint on this column contains the corresponding given constraint
    CColRefSetIter crsi(*m_pcrsUsed);
    while (fContains && crsi.FAdvance())
    {
        CColRef *pcr = crsi.Pcr();
        CConstraint *pcnstrColThis = Pcnstr(m_pmp, pcr);
        GPOS_ASSERT (NULL != pcnstrColThis);
        CConstraint *pcnstrColOther = pcnstr->Pcnstr(m_pmp, pcr);

        // convert each of them to interval (if they are not already)
        CConstraintInterval *pciThis = CConstraintInterval::PciIntervalFromConstraint(m_pmp, pcnstrColThis, pcr);
        CConstraintInterval *pciOther = CConstraintInterval::PciIntervalFromConstraint(m_pmp, pcnstrColOther, pcr);

        fContains = pciThis->FContainsInterval(m_pmp, pciOther);
        pciThis->Release();
        pciOther->Release();
        pcnstrColThis->Release();
        CRefCount::SafeRelease(pcnstrColOther);
    }

    // insert containment query into the local map
#ifdef GPOS_DEBUG
    BOOL fSuccess =
#endif // GPOS_DEBUG
        m_phmcontain->FInsert(pcnstr, PfVal(fContains));
    GPOS_ASSERT(fSuccess);

    return fContains;
}
Пример #24
0
//---------------------------------------------------------------------------
//	@function:
//		CConstraint::PdrgpcnstrDeduplicate
//
//	@doc:
//		Simplify an array of constraints to be used as children for a conjunction
//		or disjunction. If there are two or more elements that reference only one
//		particular column, these constraints are combined into one
//
//---------------------------------------------------------------------------
DrgPcnstr *
CConstraint::PdrgpcnstrDeduplicate
(
    IMemoryPool *pmp,
    DrgPcnstr *pdrgpcnstr,
    EConstraintType ect
)
const
{
    DrgPcnstr *pdrgpcnstrNew = GPOS_NEW(pmp) DrgPcnstr(pmp);

    CColRefSet *pcrsDeduped = GPOS_NEW(pmp) CColRefSet(pmp);

    const ULONG ulLen = pdrgpcnstr->UlLength();
    for (ULONG ul = 0; ul < ulLen; ul++)
    {
        CConstraint *pcnstrChild = (*pdrgpcnstr)[ul];
        CColRefSet *pcrs = pcnstrChild->PcrsUsed();

        // we only simplify constraints that reference a single column, otherwise
        // we add constraint as is
        if (1 < pcrs->CElements())
        {
            pcnstrChild->AddRef();
            pdrgpcnstrNew->Append(pcnstrChild);
            continue;
        }

        CColRef *pcr = pcrs->PcrFirst();
        if (pcrsDeduped->FMember(pcr))
        {
            // current constraint has already been combined with a previous one
            continue;
        }

        // get all constraints from the input array that reference this column
        DrgPcnstr *pdrgpcnstrCol = PdrgpcnstrOnColumn(pmp, pdrgpcnstr, pcr, true /*fExclusive*/);
        if (1 == pdrgpcnstrCol->UlLength())
        {
            // if there is only one such constraint, then no simplification
            // for this column
            pdrgpcnstrCol->Release();
            pcnstrChild->AddRef();
            pdrgpcnstrNew->Append(pcnstrChild);
            continue;
        }

        CExpression *pexpr = NULL;

        if (EctConjunction == ect)
        {
            pexpr = PexprScalarConjDisj(pmp, pdrgpcnstrCol, true /*fConj*/);
        }
        else
        {
            GPOS_ASSERT(EctDisjunction == ect);
            pexpr = PexprScalarConjDisj(pmp, pdrgpcnstrCol, false /*fConj*/);
        }
        pdrgpcnstrCol->Release();
        GPOS_ASSERT(NULL != pexpr);

        CConstraint *pcnstrNew = CConstraintInterval::PciIntervalFromScalarExpr(pmp, pexpr, pcr);
        GPOS_ASSERT(NULL != pcnstrNew);
        pexpr->Release();
        pdrgpcnstrNew->Append(pcnstrNew);
        pcrsDeduped->Include(pcr);
    }

    pcrsDeduped->Release();
    pdrgpcnstr->Release();
    return pdrgpcnstrNew;
}
Пример #25
0
//---------------------------------------------------------------------------
//	@function:
//		CConstraint::PcnstrFromScalarBoolOp
//
//	@doc:
//		Create constraint from scalar boolean expression
//
//---------------------------------------------------------------------------
CConstraint *
CConstraint::PcnstrFromScalarBoolOp
(
    IMemoryPool *pmp,
    CExpression *pexpr,
    DrgPcrs **ppdrgpcrs // output equivalence classes
)
{
    GPOS_ASSERT(NULL != pexpr);
    GPOS_ASSERT(CUtils::FScalarBoolOp(pexpr));
    GPOS_ASSERT(NULL != ppdrgpcrs);
    GPOS_ASSERT(NULL == *ppdrgpcrs);

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

    const ULONG ulArity= pexpr->UlArity();
    for (ULONG ul = 0; ul < ulArity; ul++)
    {
        DrgPcrs *pdrgpcrsChild = NULL;
        CConstraint *pcnstrChild = PcnstrFromScalarExpr(pmp, (*pexpr)[ul], &pdrgpcrsChild);
        if (NULL == pcnstrChild || pcnstrChild->FUnbounded())
        {
            CRefCount::SafeRelease(pcnstrChild);
            CRefCount::SafeRelease(pdrgpcrsChild);
            if (CPredicateUtils::FOr(pexpr))
            {
                pdrgpcnstr->Release();
                return NULL;
            }
            continue;
        }
        GPOS_ASSERT(NULL != pdrgpcrsChild);

        pdrgpcnstr->Append(pcnstrChild);
        DrgPcrs *pdrgpcrsMerged = PdrgpcrsMergeFromBoolOp(pmp, pexpr, *ppdrgpcrs, pdrgpcrsChild);

        (*ppdrgpcrs)->Release();
        *ppdrgpcrs = pdrgpcrsMerged;
        pdrgpcrsChild->Release();
    }

    const ULONG ulLen = pdrgpcnstr->UlLength();
    if (0 == ulLen)
    {
        pdrgpcnstr->Release();
        return NULL;
    }

    if (1 == ulLen)
    {
        CConstraint *pcnstrChild = (*pdrgpcnstr)[0];
        pcnstrChild->AddRef();
        pdrgpcnstr->Release();

        if (CPredicateUtils::FNot(pexpr))
        {
            return GPOS_NEW(pmp) CConstraintNegation(pmp, pcnstrChild);
        }

        return pcnstrChild;
    }

    // we know we have more than one child
    if (CPredicateUtils::FAnd(pexpr))
    {
        return GPOS_NEW(pmp) CConstraintConjunction(pmp, pdrgpcnstr);
    }

    if (CPredicateUtils::FOr(pexpr))
    {
        return GPOS_NEW(pmp) CConstraintDisjunction(pmp, pdrgpcnstr);
    }

    return NULL;
}
Пример #26
0
//---------------------------------------------------------------------------
//	@function:
//		CLogical::PpcDeriveConstraintRestrict
//
//	@doc:
//		Derive constraint property only on the given columns
//
//---------------------------------------------------------------------------
CPropConstraint *
CLogical::PpcDeriveConstraintRestrict
	(
	IMemoryPool *pmp,
	CExpressionHandle &exprhdl,
	CColRefSet *pcrsOutput
	)
{
	// constraint property from relational child
	CPropConstraint *ppc = exprhdl.Pdprel(0)->Ppc();
	DrgPcrs *pdrgpcrs = ppc->PdrgpcrsEquivClasses();

	// construct new array of equivalence classes
	DrgPcrs *pdrgpcrsNew = GPOS_NEW(pmp) DrgPcrs(pmp);

	const ULONG ulLen = pdrgpcrs->UlLength();
	for (ULONG ul = 0; ul < ulLen; ul++)
	{
		CColRefSet *pcrsEquiv = GPOS_NEW(pmp) CColRefSet(pmp);
		pcrsEquiv->Include((*pdrgpcrs)[ul]);
		pcrsEquiv->Intersection(pcrsOutput);

		if (0 < pcrsEquiv->CElements())
		{
			pdrgpcrsNew->Append(pcrsEquiv);
		}
		else
		{
			pcrsEquiv->Release();
		}
	}

	CConstraint *pcnstrChild = ppc->Pcnstr();
	if (NULL == pcnstrChild)
	{
		return GPOS_NEW(pmp) CPropConstraint(pmp, pdrgpcrsNew, NULL);
	}

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

	// include only constraints on given columns
	CColRefSetIter crsi(*pcrsOutput);
	while (crsi.FAdvance())
	{
		CColRef *pcr = crsi.Pcr();
		CConstraint *pcnstrCol = pcnstrChild->Pcnstr(pmp, pcr);
		if (NULL == pcnstrCol)
		{
			continue;
		}

		if (pcnstrCol->FUnbounded())
		{
			pcnstrCol->Release();
			continue;
		}

		pdrgpcnstr->Append(pcnstrCol);
	}

	CConstraint *pcnstr = CConstraint::PcnstrConjunction(pmp, pdrgpcnstr);

	return GPOS_NEW(pmp) CPropConstraint(pmp, pdrgpcrsNew, pcnstr);
}
Пример #27
0
//---------------------------------------------------------------------------
//	@function:
//		CLogical::PpcDeriveConstraintFromPredicates
//
//	@doc:
//		Derive constraint property when expression has relational children and
//		scalar children (predicates)
//
//---------------------------------------------------------------------------
CPropConstraint *
CLogical::PpcDeriveConstraintFromPredicates
	(
	IMemoryPool *pmp,
	CExpressionHandle &exprhdl
	)
{
	DrgPcrs *pdrgpcrs = GPOS_NEW(pmp) DrgPcrs(pmp);

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

	// collect constraint properties from relational children
	// and predicates from scalar children
	const ULONG ulArity = exprhdl.UlArity();
	for (ULONG ul = 0; ul < ulArity; ul++)
	{
		if (exprhdl.FScalarChild(ul))
		{
			CExpression *pexprScalar = exprhdl.PexprScalarChild(ul);

			// make sure it is a predicate... boolop, cmp, nulltest
			if (NULL == pexprScalar || !CUtils::FPredicate(pexprScalar))
			{
				continue;
			}

			DrgPcrs *pdrgpcrsChild = NULL;
			CConstraint *pcnstr = CConstraint::PcnstrFromScalarExpr(pmp, pexprScalar, &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);
		}
		else
		{
			CDrvdPropRelational *pdprel = exprhdl.Pdprel(ul);
			CPropConstraint *ppc = pdprel->Ppc();

			// equivalence classes coming from child
			DrgPcrs *pdrgpcrsChild = ppc->PdrgpcrsEquivClasses();

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

			// constraint coming from child
			CConstraint *pcnstr = ppc->Pcnstr();
			if (NULL != pcnstr)
			{
				pcnstr->AddRef();
				pdrgpcnstr->Append(pcnstr);
			}
		}
	}

	CConstraint *pcnstrNew = CConstraint::PcnstrConjunction(pmp, pdrgpcnstr);

	return GPOS_NEW(pmp) CPropConstraint(pmp, pdrgpcrs, pcnstrNew);
}
Пример #28
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;
}
Пример #29
0
//---------------------------------------------------------------------------
//	@function:
//		CPartConstraint::PpartcnstrDisjunction
//
//	@doc:
//		Construct a disjunction of the two part constraints. We can only
//		construct this disjunction if they differ only on the last level
//
//---------------------------------------------------------------------------
CPartConstraint *
CPartConstraint::PpartcnstrDisjunction
	(
	IMemoryPool *mp,
	CPartConstraint *ppartcnstrFst,
	CPartConstraint *ppartcnstrSnd
	)
{
	GPOS_ASSERT(NULL != ppartcnstrFst);
	GPOS_ASSERT(NULL != ppartcnstrSnd);

	if (ppartcnstrFst->IsConstraintUnbounded())
	{
		ppartcnstrFst->AddRef();
		return ppartcnstrFst;
	}
	
	if (ppartcnstrSnd->IsConstraintUnbounded())
	{
		ppartcnstrSnd->AddRef();
		return ppartcnstrSnd;
	}

	if (!FDisjunctionPossible(ppartcnstrFst, ppartcnstrSnd))
	{
		return NULL;
	}

	UlongToConstraintMap *phmulcnstr = GPOS_NEW(mp) UlongToConstraintMap(mp);
	CBitSet *pbsCombined = GPOS_NEW(mp) CBitSet(mp);

	const ULONG ulLevels = ppartcnstrFst->m_num_of_part_levels;
	for (ULONG ul = 0; ul < ulLevels-1; ul++)
	{
		CConstraint *pcnstrFst = ppartcnstrFst->Pcnstr(ul);

		pcnstrFst->AddRef();
#ifdef GPOS_DEBUG
		BOOL result =
#endif // GPOS_DEBUG
		phmulcnstr->Insert(GPOS_NEW(mp) ULONG(ul), pcnstrFst);
		GPOS_ASSERT(result);

		if (ppartcnstrFst->IsDefaultPartition(ul))
		{
			pbsCombined->ExchangeSet(ul);
		}
	}

	// create the disjunction between the constraints of the last level
	CConstraint *pcnstrFst = ppartcnstrFst->Pcnstr(ulLevels - 1);
	CConstraint *pcnstrSnd = ppartcnstrSnd->Pcnstr(ulLevels - 1);

	pcnstrFst->AddRef();
	pcnstrSnd->AddRef();
	CConstraintArray *pdrgpcnstrCombined = GPOS_NEW(mp) CConstraintArray(mp);
	
	pdrgpcnstrCombined->Append(pcnstrFst);
	pdrgpcnstrCombined->Append(pcnstrSnd);

	CConstraint *pcnstrDisj = CConstraint::PcnstrDisjunction(mp, pdrgpcnstrCombined);
	GPOS_ASSERT(NULL != pcnstrDisj);
#ifdef GPOS_DEBUG
	BOOL result =
#endif // GPOS_DEBUG
	phmulcnstr->Insert(GPOS_NEW(mp) ULONG(ulLevels - 1), pcnstrDisj);
	GPOS_ASSERT(result);

	if (ppartcnstrFst->IsDefaultPartition(ulLevels - 1) || ppartcnstrSnd->IsDefaultPartition(ulLevels - 1))
	{
		pbsCombined->ExchangeSet(ulLevels - 1);
	}

	CColRef2dArray *pdrgpdrgpcr = ppartcnstrFst->Pdrgpdrgpcr();
	pdrgpdrgpcr->AddRef();
	return GPOS_NEW(mp) CPartConstraint(mp, phmulcnstr, pbsCombined, false /*is_unbounded*/, pdrgpdrgpcr);
}