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