Ejemplo n.º 1
0
//---------------------------------------------------------------------------
//	@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];

        const ULONG ulArity = pexprArray->UlArity();

        // 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++)
        {
            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;
}