Exemplo n.º 1
0
//---------------------------------------------------------------------------
//	@function:
//		CConstraint::PcnstrConjDisjRemapForColumn
//
//	@doc:
//		Return a copy of the conjunction/disjunction constraint for a different column
//
//---------------------------------------------------------------------------
CConstraint *
CConstraint::PcnstrConjDisjRemapForColumn
(
    IMemoryPool *pmp,
    CColRef *pcr,
    DrgPcnstr *pdrgpcnstr,
    BOOL fConj
)
const
{
    GPOS_ASSERT(NULL != pcr);

    DrgPcnstr *pdrgpcnstrNew = GPOS_NEW(pmp) DrgPcnstr(pmp);

    const ULONG ulLen = pdrgpcnstr->UlLength();
    for (ULONG ul = 0; ul < ulLen; ul++)
    {
        // clone child
        CConstraint *pcnstrChild = (*pdrgpcnstr)[ul]->PcnstrRemapForColumn(pmp, pcr);
        GPOS_ASSERT(NULL != pcnstrChild);

        pdrgpcnstrNew->Append(pcnstrChild);
    }

    if (fConj)
    {
        return PcnstrConjunction(pmp, pdrgpcnstrNew);
    }
    return PcnstrDisjunction(pmp, pdrgpcnstrNew);
}
// mapping between columns and single column constraints in array of constraints
static
HMColConstr *
PhmcolconstrSingleColConstr
	(
		IMemoryPool *pmp,
		DrgPcnstr *drgPcnstr
	)
{
	CAutoRef<DrgPcnstr> arpdrgpcnstr(drgPcnstr);
	HMColConstr *phmcolconstr = GPOS_NEW(pmp) HMColConstr(pmp);

	const ULONG ulLen = arpdrgpcnstr->UlLength();

	for (ULONG ul = 0; ul < ulLen; ul++)
	{
		CConstraint *pcnstrChild = (*arpdrgpcnstr)[ul];
		CColRefSet *pcrs = pcnstrChild->PcrsUsed();

		if (1 == pcrs->CElements())
		{
			CColRef *pcr = pcrs->PcrFirst();
			DrgPcnstr *pcnstrMapped = phmcolconstr->PtLookup(pcr);
			if (NULL == pcnstrMapped)
			{
				pcnstrMapped = GPOS_NEW(pmp) DrgPcnstr(pmp);
				phmcolconstr->FInsert(pcr, pcnstrMapped);
			}
			pcnstrChild->AddRef();
			pcnstrMapped->Append(pcnstrChild);
		}
	}

	return phmcolconstr;
}
Exemplo n.º 3
0
//---------------------------------------------------------------------------
//	@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;
}
Exemplo n.º 4
0
//---------------------------------------------------------------------------
//	@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;
}
DrgPcnstr *
CColConstraintsHashMapper::PdrgPcnstrLookup
	(
		CColRef *pcr
	)
{
	DrgPcnstr *pdrgpcnstrCol = m_phmColConstr->PtLookup(pcr);
	pdrgpcnstrCol->AddRef();
	return pdrgpcnstrCol;
}
Exemplo n.º 6
0
//---------------------------------------------------------------------------
//	@function:
//		CConstraint::PcnstrFromScalarCmp
//
//	@doc:
//		Create constraint from scalar comparison
//
//---------------------------------------------------------------------------
CConstraint *
CConstraint::PcnstrFromScalarCmp
(
    IMemoryPool *pmp,
    CExpression *pexpr,
    DrgPcrs **ppdrgpcrs // output equivalence classes
)
{
    GPOS_ASSERT(NULL != pexpr);
    GPOS_ASSERT(CUtils::FScalarCmp(pexpr));
    GPOS_ASSERT(NULL != ppdrgpcrs);
    GPOS_ASSERT(NULL == *ppdrgpcrs);

    CExpression *pexprLeft = (*pexpr)[0];
    CExpression *pexprRight = (*pexpr)[1];

    // check if the scalar comparison is over scalar idents
    if (COperator::EopScalarIdent == pexprLeft->Pop()->Eopid()
            && COperator::EopScalarIdent == pexprRight->Pop()->Eopid())
    {
        CScalarIdent *popScIdLeft = CScalarIdent::PopConvert((*pexpr)[0]->Pop());
        const CColRef *pcrLeft =  popScIdLeft->Pcr();

        CScalarIdent *popScIdRight = CScalarIdent::PopConvert((*pexpr)[1]->Pop());
        const CColRef *pcrRight =  popScIdRight->Pcr();

        if (!CUtils::FConstrainableType(pcrLeft->Pmdtype()->Pmdid()) ||
                !CUtils::FConstrainableType(pcrRight->Pmdtype()->Pmdid()))
        {
            return NULL;
        }

        *ppdrgpcrs = GPOS_NEW(pmp) DrgPcrs(pmp);
        if (CPredicateUtils::FEquality(pexpr))
        {
            // col1 = col2
            CColRefSet *pcrsNew = GPOS_NEW(pmp) CColRefSet(pmp);
            pcrsNew->Include(pcrLeft);
            pcrsNew->Include(pcrRight);

            (*ppdrgpcrs)->Append(pcrsNew);
        }

        // create NOT NULL constraints to both columns
        DrgPcnstr *pdrgpcnstr = GPOS_NEW(pmp) DrgPcnstr(pmp);
        pdrgpcnstr->Append(CConstraintInterval::PciUnbounded(pmp, pcrLeft, false /*fIncludesNull*/));
        pdrgpcnstr->Append(CConstraintInterval::PciUnbounded(pmp, pcrRight, false /*fIncludesNull*/));
        return CConstraint::PcnstrConjunction(pmp, pdrgpcnstr);
    }

    // TODO: , May 28, 2012; add support for other cases besides (col cmp col)

    return NULL;
}
Exemplo n.º 7
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];
		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;
}
Exemplo n.º 8
0
//---------------------------------------------------------------------------
//	@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;
}
Exemplo n.º 9
0
//---------------------------------------------------------------------------
//	@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);
}
Exemplo n.º 10
0
//---------------------------------------------------------------------------
//	@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);
}
Exemplo n.º 11
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;
}
Exemplo n.º 12
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;
}
Exemplo n.º 13
0
//---------------------------------------------------------------------------
//	@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);
}
Exemplo n.º 14
0
//---------------------------------------------------------------------------
//	@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));
}
Exemplo n.º 15
0
//---------------------------------------------------------------------------
//	@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);
}
Exemplo n.º 16
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 = 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;
}