//--------------------------------------------------------------------------- // @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: // CLogicalSetOp::PdrgpcnstrColumn // // @doc: // Get constraints for a given output column from all children // //--------------------------------------------------------------------------- DrgPcnstr * CLogicalSetOp::PdrgpcnstrColumn ( IMemoryPool *pmp, CExpressionHandle &exprhdl, ULONG ulColIndex, ULONG ulStart ) const { DrgPcnstr *pdrgpcnstr = GPOS_NEW(pmp) DrgPcnstr(pmp); CColRef *pcr = (*m_pdrgpcrOutput)[ulColIndex]; if (!CUtils::FConstrainableType(pcr->Pmdtype()->Pmdid())) { return pdrgpcnstr; } const ULONG ulChildren = exprhdl.UlArity(); for (ULONG ul = ulStart; ul < ulChildren; ul++) { CConstraint *pcnstr = PcnstrColumn(pmp, exprhdl, ulColIndex, ul); if (NULL == pcnstr) { pcnstr = CConstraintInterval::PciUnbounded(pmp, pcr, true /*fIsNull*/); } GPOS_ASSERT (NULL != pcnstr); pdrgpcnstr->Append(pcnstr); } return pdrgpcnstr; }
//--------------------------------------------------------------------------- // @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: // CConstraint::PcnstrFromScalarArrayCmp // // @doc: // Create constraint from scalar array comparison expression // //--------------------------------------------------------------------------- CConstraint * CConstraint::PcnstrFromScalarArrayCmp ( IMemoryPool *pmp, CExpression *pexpr, CColRef *pcr ) { GPOS_ASSERT(NULL != pexpr); GPOS_ASSERT(CUtils::FScalarArrayCmp(pexpr)); CScalarArrayCmp *popScArrayCmp = CScalarArrayCmp::PopConvert(pexpr->Pop()); CScalarArrayCmp::EArrCmpType earrccmpt = popScArrayCmp->Earrcmpt(); if ((CScalarArrayCmp::EarrcmpAny == earrccmpt || CScalarArrayCmp::EarrcmpAll == earrccmpt) && CPredicateUtils::FCompareIdentToConstArray(pexpr)) { // column #ifdef GPOS_DEBUG CScalarIdent *popScId = CScalarIdent::PopConvert((*pexpr)[0]->Pop()); GPOS_ASSERT (pcr == (CColRef *) popScId->Pcr()); #endif // GPOS_DEBUG // get comparison type IMDType::ECmpType ecmpt = CUtils::Ecmpt(popScArrayCmp->PmdidOp()); CExpression *pexprArray = (*pexpr)[1]; DrgPcnstr *pdrgpcnstr = GPOS_NEW(pmp) DrgPcnstr(pmp); const ULONG ulArity = pexprArray->UlArity(); for (ULONG ul = 0; ul < ulArity; ul++) { GPOS_ASSERT(CUtils::FScalarConst((*pexprArray)[ul]) && "expecting a constant"); CScalarConst *popScConst = CScalarConst::PopConvert((*pexprArray)[ul]->Pop()); CConstraintInterval *pci = CConstraintInterval::PciIntervalFromColConstCmp(pmp, pcr, ecmpt, popScConst); pdrgpcnstr->Append(pci); } if (earrccmpt == CScalarArrayCmp::EarrcmpAny) { // predicate is of the form 'A IN (1,2,3)' // return a disjunction of ranges {[1,1], [2,2], [3,3]} return GPOS_NEW(pmp) CConstraintDisjunction(pmp, pdrgpcnstr); } // predicate is of the form 'A NOT IN (1,2,3)' // return a conjunctive negation on {[1,1], [2,2], [3,3]} return GPOS_NEW(pmp) CConstraintConjunction(pmp, pdrgpcnstr); } return NULL; }
//--------------------------------------------------------------------------- // @function: // CLogicalSetOp::PpcDeriveConstraintIntersectUnion // // @doc: // Derive constraint property for intersect and union operators // //--------------------------------------------------------------------------- CPropConstraint * CLogicalSetOp::PpcDeriveConstraintIntersectUnion ( IMemoryPool *pmp, CExpressionHandle &exprhdl, BOOL fIntersect ) const { const ULONG ulCols = m_pdrgpcrOutput->UlLength(); DrgPcnstr *pdrgpcnstr = GPOS_NEW(pmp) DrgPcnstr(pmp); for (ULONG ul = 0; ul < ulCols; ul++) { // get constraints for this column from all children DrgPcnstr *pdrgpcnstrCol = PdrgpcnstrColumn(pmp, exprhdl, ul, 0 /*ulStart*/); CConstraint *pcnstrCol = NULL; if (fIntersect) { pcnstrCol = CConstraint::PcnstrConjunction(pmp, pdrgpcnstrCol); } else { pcnstrCol = CConstraint::PcnstrDisjunction(pmp, pdrgpcnstrCol); } if (NULL != pcnstrCol) { pdrgpcnstr->Append(pcnstrCol); } } CConstraint *pcnstrAll = CConstraint::PcnstrConjunction(pmp, pdrgpcnstr); DrgPcrs *pdrgpcrs = PdrgpcrsOutputEquivClasses(pmp, exprhdl, fIntersect); return GPOS_NEW(pmp) CPropConstraint(pmp, pdrgpcrs, pcnstrAll); }
//--------------------------------------------------------------------------- // @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: // 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::PpcDeriveConstraintFromTable // // @doc: // Derive constraint property from a table/index get // //--------------------------------------------------------------------------- CPropConstraint * CLogical::PpcDeriveConstraintFromTable ( IMemoryPool *pmp, const CTableDescriptor *ptabdesc, const DrgPcr *pdrgpcrOutput ) { DrgPcrs *pdrgpcrs = GPOS_NEW(pmp) DrgPcrs(pmp); DrgPcnstr *pdrgpcnstr = GPOS_NEW(pmp) DrgPcnstr(pmp); const DrgPcoldesc *pdrgpcoldesc = ptabdesc->Pdrgpcoldesc(); const ULONG ulCols = pdrgpcoldesc->UlLength(); DrgPcr *pdrgpcrNonSystem = GPOS_NEW(pmp) DrgPcr(pmp); for (ULONG ul = 0; ul < ulCols; ul++) { CColumnDescriptor *pcoldesc = (*pdrgpcoldesc)[ul]; CColRef *pcr = (*pdrgpcrOutput)[ul]; // we are only interested in non-system columns that are defined as // being NOT NULL if (pcoldesc->FSystemColumn()) { continue; } pdrgpcrNonSystem->Append(pcr); if (pcoldesc->FNullable()) { continue; } // add a "not null" constraint and an equivalence class CConstraint * pcnstr = CConstraintInterval::PciUnbounded(pmp, pcr, false /*fIncludesNull*/); if (pcnstr == NULL) { continue; } pdrgpcnstr->Append(pcnstr); CColRefSet *pcrsEquiv = GPOS_NEW(pmp) CColRefSet(pmp); pcrsEquiv->Include(pcr); pdrgpcrs->Append(pcrsEquiv); } CMDAccessor *pmda = COptCtxt::PoctxtFromTLS()->Pmda(); const IMDRelation *pmdrel = pmda->Pmdrel(ptabdesc->Pmdid()); const ULONG ulCheckConstraint = pmdrel->UlCheckConstraints(); for (ULONG ul = 0; ul < ulCheckConstraint; ul++) { IMDId *pmdidCheckConstraint = pmdrel->PmdidCheckConstraint(ul); const IMDCheckConstraint *pmdCheckConstraint = pmda->Pmdcheckconstraint(pmdidCheckConstraint); // extract the check constraint expression CExpression *pexprCheckConstraint = pmdCheckConstraint->Pexpr(pmp, pmda, pdrgpcrNonSystem); GPOS_ASSERT(NULL != pexprCheckConstraint); GPOS_ASSERT(CUtils::FPredicate(pexprCheckConstraint)); DrgPcrs *pdrgpcrsChild = NULL; CConstraint *pcnstr = CConstraint::PcnstrFromScalarExpr(pmp, pexprCheckConstraint, &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); pexprCheckConstraint->Release(); } pdrgpcrNonSystem->Release(); return GPOS_NEW(pmp) CPropConstraint(pmp, pdrgpcrs, CConstraint::PcnstrConjunction(pmp, pdrgpcnstr)); }
//--------------------------------------------------------------------------- // @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: // CConstraint::PcnstrFromScalarArrayCmp // // @doc: // Create constraint from scalar array comparison expression // //--------------------------------------------------------------------------- CConstraint * CConstraint::PcnstrFromScalarArrayCmp ( IMemoryPool *pmp, CExpression *pexpr, CColRef *pcr ) { GPOS_ASSERT(NULL != pexpr); GPOS_ASSERT(CUtils::FScalarArrayCmp(pexpr)); CScalarArrayCmp *popScArrayCmp = CScalarArrayCmp::PopConvert(pexpr->Pop()); CScalarArrayCmp::EArrCmpType earrccmpt = popScArrayCmp->Earrcmpt(); if ((CScalarArrayCmp::EarrcmpAny == earrccmpt || CScalarArrayCmp::EarrcmpAll == earrccmpt) && CPredicateUtils::FCompareIdentToConstArray(pexpr)) { // column #ifdef GPOS_DEBUG CScalarIdent *popScId = CScalarIdent::PopConvert((*pexpr)[0]->Pop()); GPOS_ASSERT (pcr == (CColRef *) popScId->Pcr()); #endif // GPOS_DEBUG // get comparison type IMDType::ECmpType ecmpt = CUtils::Ecmpt(popScArrayCmp->PmdidOp()); CExpression *pexprArray = CUtils::PexprScalarArrayChild(pexpr); const ULONG ulArity = CUtils::UlScalarArrayArity(pexprArray); // When array size exceeds the threshold, don't expand it into a DNF COptimizerConfig *poconf = COptCtxt::PoctxtFromTLS()->Poconf(); ULONG ulArrayExpansionThreshold = poconf->Phint()->UlArrayExpansionThreshold(); if (ulArity > ulArrayExpansionThreshold) { return NULL; } DrgPcnstr *pdrgpcnstr = GPOS_NEW(pmp) DrgPcnstr(pmp); for (ULONG ul = 0; ul < ulArity; ul++) { CScalarConst *popScConst = CUtils::PScalarArrayConstChildAt(pexprArray,ul); CConstraintInterval *pci = CConstraintInterval::PciIntervalFromColConstCmp(pmp, pcr, ecmpt, popScConst); pdrgpcnstr->Append(pci); } if (earrccmpt == CScalarArrayCmp::EarrcmpAny) { // predicate is of the form 'A IN (1,2,3)' // return a disjunction of ranges {[1,1], [2,2], [3,3]} return GPOS_NEW(pmp) CConstraintDisjunction(pmp, pdrgpcnstr); } // predicate is of the form 'A NOT IN (1,2,3)' // return a conjunctive negation on {[1,1], [2,2], [3,3]} return GPOS_NEW(pmp) CConstraintConjunction(pmp, pdrgpcnstr); } return NULL; }