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