Esempio n. 1
0
//---------------------------------------------------------------------------
//	@function:
//		CStatsPredUtils::Pdrgpstatsjoin
//
//	@doc:
//		Extract statistics join information
//
//---------------------------------------------------------------------------
DrgPstatsjoin *
CStatsPredUtils::Pdrgpstatsjoin
	(
	IMemoryPool *pmp,
	CExpressionHandle &exprhdl
	)
{
	// in case of subquery in join predicate, we return empty stats
	if (exprhdl.Pdpscalar(exprhdl.UlArity() - 1)->FHasSubquery())
	{
		return GPOS_NEW(pmp) DrgPstatsjoin(pmp);
	}

	DrgPcrs *pdrgpcrsOutput = GPOS_NEW(pmp) DrgPcrs(pmp);
	const ULONG ulSize = exprhdl.UlArity();
	for (ULONG ul = 0; ul < ulSize - 1; ul++)
	{
		CColRefSet *pcrs = exprhdl.Pdprel(ul)->PcrsOutput();
		pcrs->AddRef();
		pdrgpcrsOutput->Append(pcrs);
	}

	// TODO:  02/29/2012 replace with constraint property info once available
	CExpression *pexprScalar = exprhdl.PexprScalarChild(exprhdl.UlArity() - 1);
	CColRefSet *pcrsOuterRefs = exprhdl.Pdprel()->PcrsOuter();

	DrgPstatsjoin *pdrgpstats = Pdrgpstatsjoin(pmp, exprhdl, pexprScalar, pdrgpcrsOutput, pcrsOuterRefs);

	// clean up
	pdrgpcrsOutput->Release();

	return pdrgpstats;
}
Esempio n. 2
0
//---------------------------------------------------------------------------
//	@function:
//		CLogicalSetOp::PdrgpcrsInputMapped
//
//	@doc:
//		Get equivalence classes from one input child, mapped to output columns
//
//---------------------------------------------------------------------------
DrgPcrs *
CLogicalSetOp::PdrgpcrsInputMapped
	(
	IMemoryPool *pmp,
	CExpressionHandle &exprhdl,
	ULONG ulChild
	)
	const
{
	DrgPcrs *pdrgpcrsInput = exprhdl.Pdprel(ulChild)->Ppc()->PdrgpcrsEquivClasses();
	const ULONG ulLen = pdrgpcrsInput->UlLength();

	CColRefSet* pcrsChildInput = (*m_pdrgpcrsInput)[ulChild];
	DrgPcrs *pdrgpcrs = GPOS_NEW(pmp) DrgPcrs(pmp);
	for (ULONG ul = 0; ul < ulLen; ul++)
	{
		CColRefSet *pcrs = GPOS_NEW(pmp) CColRefSet(pmp);
		pcrs->Include((*pdrgpcrsInput)[ul]);
		pcrs->Intersection(pcrsChildInput);

		if (0 == pcrs->CElements())
		{
			pcrs->Release();
			continue;
		}

		// replace each input column with its corresponding output column
		pcrs->Replace((*m_pdrgpdrgpcrInput)[ulChild], m_pdrgpcrOutput);

		pdrgpcrs->Append(pcrs);
	}

	return pdrgpcrs;
}
Esempio n. 3
0
//---------------------------------------------------------------------------
//	@function:
//		CLogicalDifferenceAll::PstatsDerive
//
//	@doc:
//		Derive statistics
//
//---------------------------------------------------------------------------
IStatistics *
CLogicalDifferenceAll::PstatsDerive
	(
	IMemoryPool *pmp,
	CExpressionHandle &exprhdl,
	DrgPstat * // not used
	)
	const
{
	GPOS_ASSERT(Esp(exprhdl) > EspNone);

	// difference all is transformed into a LASJ,
	// we follow the same route to compute statistics
	DrgPcrs *pdrgpcrsOutput = GPOS_NEW(pmp) DrgPcrs(pmp);
	const ULONG ulSize = m_pdrgpdrgpcrInput->UlLength();
	for (ULONG ul = 0; ul < ulSize; ul++)
	{
		CColRefSet *pcrs = GPOS_NEW(pmp) CColRefSet(pmp, (*m_pdrgpdrgpcrInput)[ul]);
		pdrgpcrsOutput->Append(pcrs);
	}

	IStatistics *pstatsOuter = exprhdl.Pstats(0);
	IStatistics *pstatsInner = exprhdl.Pstats(1);

	// construct the scalar condition for the LASJ
	CExpression *pexprScCond = CUtils::PexprConjINDFCond(pmp, m_pdrgpdrgpcrInput);

	// compute the statistics for LASJ
	CColRefSet *pcrsOuterRefs = exprhdl.Pdprel()->PcrsOuter();
	DrgPstatsjoin *pdrgpstatsjoin = CStatsPredUtils::Pdrgpstatsjoin
														(
														pmp, 
														exprhdl, 
														pexprScCond, 
														pdrgpcrsOutput, 
														pcrsOuterRefs
														);
	IStatistics *pstatsLASJ = pstatsOuter->PstatsLASJoin
											(
											pmp,
											pstatsInner,
											pdrgpstatsjoin,
											true /* fIgnoreLasjHistComputation*/
											);

	// clean up
	pexprScCond->Release();
	pdrgpstatsjoin->Release();
	pdrgpcrsOutput->Release();

	return pstatsLASJ;
}
Esempio n. 4
0
//---------------------------------------------------------------------------
//	@function:
//		CLogicalSetOp::PdrgpcrsOutputEquivClasses
//
//	@doc:
//		Get output equivalence classes
//
//---------------------------------------------------------------------------
DrgPcrs *
CLogicalSetOp::PdrgpcrsOutputEquivClasses
	(
	IMemoryPool *pmp,
	CExpressionHandle &exprhdl,
	BOOL fIntersect
	)
	const
{
	const ULONG ulChildren = exprhdl.UlArity();
	DrgPcrs *pdrgpcrs = PdrgpcrsInputMapped(pmp, exprhdl, 0 /*ulChild*/);

	for (ULONG ul = 1; ul < ulChildren; ul++)
	{
		DrgPcrs *pdrgpcrsChild = PdrgpcrsInputMapped(pmp, exprhdl, ul);
		DrgPcrs *pdrgpcrsMerged = NULL;

		if (fIntersect)
		{
			// merge with the equivalence classes we have so far
			pdrgpcrsMerged = CUtils::PdrgpcrsMergeEquivClasses(pmp, pdrgpcrs, pdrgpcrsChild);
		}
		else
		{
			// in case of a union, an equivalence class must be coming from all
			// children to be part of the output
			pdrgpcrsMerged = CUtils::PdrgpcrsIntersectEquivClasses(pmp, pdrgpcrs, pdrgpcrsChild);

		}
		pdrgpcrsChild->Release();
		pdrgpcrs->Release();
		pdrgpcrs = pdrgpcrsMerged;
	}

	return pdrgpcrs;
}
Esempio n. 5
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;
}
Esempio n. 6
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);
}
Esempio n. 7
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));
}
Esempio n. 8
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);
}
Esempio n. 9
0
//---------------------------------------------------------------------------
//	@function:
//		CLogicalDifference::PstatsDerive
//
//	@doc:
//		Derive statistics
//
//---------------------------------------------------------------------------
IStatistics *
CLogicalDifference::PstatsDerive
(
    IMemoryPool *pmp,
    CExpressionHandle &exprhdl,
    DrgPstat * // not used
)
const
{
    GPOS_ASSERT(Esp(exprhdl) > EspNone);

    // difference is transformed into an aggregate over a LASJ,
    // we follow the same route to compute statistics
    DrgPcrs *pdrgpcrsOutput = GPOS_NEW(pmp) DrgPcrs(pmp);
    const ULONG ulSize = m_pdrgpdrgpcrInput->UlLength();
    for (ULONG ul = 0; ul < ulSize; ul++)
    {
        CColRefSet *pcrs = GPOS_NEW(pmp) CColRefSet(pmp, (*m_pdrgpdrgpcrInput)[ul]);
        pdrgpcrsOutput->Append(pcrs);
    }

    IStatistics *pstatsOuter = exprhdl.Pstats(0);
    IStatistics *pstatsInner = exprhdl.Pstats(1);

    // construct the scalar condition for the LASJ
    CExpression *pexprScCond = CUtils::PexprConjINDFCond(pmp, m_pdrgpdrgpcrInput);

    // compute the statistics for LASJ
    CColRefSet *pcrsOuterRefs = exprhdl.Pdprel()->PcrsOuter();
    DrgPstatsjoin *pdrgpstatsjoin = CStatsPredUtils::Pdrgpstatsjoin
                                    (
                                        pmp,
                                        exprhdl,
                                        pexprScCond,
                                        pdrgpcrsOutput,
                                        pcrsOuterRefs
                                    );
    IStatistics *pstatsLASJ = pstatsOuter->PstatsLASJoin
                              (
                                  pmp,
                                  pstatsInner,
                                  pdrgpstatsjoin,
                                  true /* fIgnoreLasjHistComputation */
                              );

    // clean up
    pexprScCond->Release();
    pdrgpstatsjoin->Release();

    // computed columns
    DrgPul *pdrgpulComputedCols = GPOS_NEW(pmp) DrgPul(pmp);
    IStatistics *pstats = CLogicalGbAgg::PstatsDerive
                          (
                              pmp,
                              pstatsLASJ,
                              (*m_pdrgpdrgpcrInput)[0], // we group by the columns of the first child
                              pdrgpulComputedCols, // no computed columns for set ops
                              NULL // no keys, use all grouping cols
                          );

    // clean up
    pdrgpulComputedCols->Release();
    pstatsLASJ->Release();
    pdrgpcrsOutput->Release();

    return pstats;
}