//--------------------------------------------------------------------------- // @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); }
//--------------------------------------------------------------------------- // @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; }
//--------------------------------------------------------------------------- // @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; }
//--------------------------------------------------------------------------- // @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; }
//--------------------------------------------------------------------------- // @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); }
//--------------------------------------------------------------------------- // @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); }
//--------------------------------------------------------------------------- // @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; }
//--------------------------------------------------------------------------- // @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; }
//--------------------------------------------------------------------------- // @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); }
//--------------------------------------------------------------------------- // @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; }
//--------------------------------------------------------------------------- // @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)); }
//--------------------------------------------------------------------------- // @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); }
void CSimuEntity::applyAllPositionConstraints(const double ¤t_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); } } }
//--------------------------------------------------------------------------- // @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; }
//--------------------------------------------------------------------------- // @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); }
//--------------------------------------------------------------------------- // @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; }
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; }
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; }
//--------------------------------------------------------------------------- // @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); }
//--------------------------------------------------------------------------- // @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); }
//--------------------------------------------------------------------------- // @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; }
//--------------------------------------------------------------------------- // @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; }
//--------------------------------------------------------------------------- // @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; }
//--------------------------------------------------------------------------- // @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; }
//--------------------------------------------------------------------------- // @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); }
//--------------------------------------------------------------------------- // @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); }
//--------------------------------------------------------------------------- // @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; }
//--------------------------------------------------------------------------- // @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); }