Пример #1
0
//---------------------------------------------------------------------------
//	@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;
}
Пример #2
0
//---------------------------------------------------------------------------
//	@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;
}