//--------------------------------------------------------------------------- // @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: // 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; }
//--------------------------------------------------------------------------- // @function: // CStatsPredUtils::ProcessArrayCmp // // @doc: // Extract statistics filtering information from scalar array comparison //--------------------------------------------------------------------------- void CStatsPredUtils::ProcessArrayCmp ( IMemoryPool *pmp, CExpression *pexprPred, DrgPstatspred *pdrgpstatspred ) { GPOS_ASSERT(NULL != pdrgpstatspred); GPOS_ASSERT(NULL != pexprPred); GPOS_ASSERT(2 == pexprPred->UlArity()); CScalarArrayCmp *popScArrayCmp = CScalarArrayCmp::PopConvert(pexprPred->Pop()); CExpression *pexprLeft = (*pexprPred)[0]; CExpression *pexprRight = (*pexprPred)[1]; BOOL fCompareToConst = ((COperator::EopScalarIdent == pexprLeft->Pop()->Eopid()) && (COperator::EopScalarArray == pexprRight->Pop()->Eopid())); if (!fCompareToConst) { // unsupported predicate for stats calculations pdrgpstatspred->Append(GPOS_NEW(pmp) CStatsPredUnsupported(ULONG_MAX, CStatsPred::EstatscmptOther)); return; } BOOL fAny = (CScalarArrayCmp::EarrcmpAny == popScArrayCmp->Earrcmpt()); DrgPstatspred *pdrgpstatspredChild = pdrgpstatspred; if (fAny) { pdrgpstatspredChild = GPOS_NEW(pmp) DrgPstatspred(pmp); } const ULONG ulConstants = pexprRight->UlArity(); // comparison semantics for statistics purposes is looser than regular comparison. CStatsPred::EStatsCmpType escmpt = Estatscmptype(popScArrayCmp->PmdidOp()); CScalarIdent *popScalarIdent = CScalarIdent::PopConvert(pexprLeft->Pop()); const CColRef *pcr = popScalarIdent->Pcr(); if (!CHistogram::FSupportsFilter(escmpt)) { // unsupported predicate for stats calculations pdrgpstatspred->Append(GPOS_NEW(pmp) CStatsPredUnsupported(pcr->UlId(), escmpt)); return; } for (ULONG ul = 0; ul < ulConstants; ul++) { CExpression *pexprConst = (*pexprRight)[ul]; if (COperator::EopScalarConst == pexprConst->Pop()->Eopid()) { CScalarConst *popScalarConst = CScalarConst::PopConvert(pexprConst->Pop()); IDatum *pdatumLiteral = popScalarConst->Pdatum(); CStatsPred *pstatspredChild = NULL; if (!pdatumLiteral->FStatsComparable(pdatumLiteral)) { // stats calculations on such datums unsupported pstatspredChild = GPOS_NEW(pmp) CStatsPredUnsupported(pcr->UlId(), escmpt); } else { pstatspredChild = GPOS_NEW(pmp) CStatsPredPoint(pmp, pcr, escmpt, pdatumLiteral); } pdrgpstatspredChild->Append(pstatspredChild); } } if (fAny) { CStatsPredDisj *pstatspredOr = GPOS_NEW(pmp) CStatsPredDisj(pdrgpstatspredChild); pdrgpstatspred->Append(pstatspredOr); } }