//--------------------------------------------------------------------------- // @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::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: // 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: // 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); }