示例#1
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;
}
// 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;
}
示例#3
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;
}
示例#4
0
//---------------------------------------------------------------------------
//	@function:
//		CPhysicalJoin::FHashJoinCompatible
//
//	@doc:
//		Are the given predicate parts hash join compatible?
//		predicate parts are obtained by splitting equality into outer
//		and inner expressions
//
//---------------------------------------------------------------------------
BOOL
CPhysicalJoin::FHashJoinCompatible
	(
	CExpression *pexprOuter,	// outer child of the join
	CExpression* pexprInner,	// inner child of the join
	CExpression *pexprPredOuter,// outer part of join predicate
	CExpression *pexprPredInner // inner part of join predicate
	)
{
	GPOS_ASSERT(NULL != pexprOuter);
	GPOS_ASSERT(NULL != pexprInner);
	GPOS_ASSERT(NULL != pexprPredOuter);
	GPOS_ASSERT(NULL != pexprPredInner);

	IMDId *pmdidTypeOuter = CScalar::PopConvert(pexprPredOuter->Pop())->PmdidType();
	IMDId *pmdidTypeInner = CScalar::PopConvert(pexprPredInner->Pop())->PmdidType();

	CColRefSet *pcrsUsedPredOuter = CDrvdPropScalar::Pdpscalar(pexprPredOuter->PdpDerive())->PcrsUsed();
	CColRefSet *pcrsUsedPredInner = CDrvdPropScalar::Pdpscalar(pexprPredInner->PdpDerive())->PcrsUsed();

	CColRefSet *pcrsOuter = CDrvdPropRelational::Pdprel(pexprOuter->Pdp(CDrvdProp::EptRelational))->PcrsOutput();
	CColRefSet *pcrsInner = CDrvdPropRelational::Pdprel(pexprInner->Pdp(CDrvdProp::EptRelational))->PcrsOutput();

	// make sure that each predicate child uses columns from a different join child
	// in order to reject predicates of the form 'X Join Y on f(X.a, Y.b) = 5'
	BOOL fPredOuterUsesJoinOuterChild = (0 < pcrsUsedPredOuter->CElements()) && pcrsOuter->FSubset(pcrsUsedPredOuter);
	BOOL fPredOuterUsesJoinInnerChild = (0 < pcrsUsedPredOuter->CElements()) && pcrsInner->FSubset(pcrsUsedPredOuter);
	BOOL fPredInnerUsesJoinOuterChild = (0 < pcrsUsedPredInner->CElements()) && pcrsOuter->FSubset(pcrsUsedPredInner);
	BOOL fPredInnerUsesJoinInnerChild = (0 < pcrsUsedPredInner->CElements()) && pcrsInner->FSubset(pcrsUsedPredInner);

	BOOL fHashJoinCompatiblePred =
		(fPredOuterUsesJoinOuterChild && fPredInnerUsesJoinInnerChild) ||
		(fPredOuterUsesJoinInnerChild && fPredInnerUsesJoinOuterChild);

	CMDAccessor *pmda = COptCtxt::PoctxtFromTLS()->Pmda();

	return fHashJoinCompatiblePred &&
					pmda->Pmdtype(pmdidTypeOuter)->FHashable() &&
					pmda->Pmdtype(pmdidTypeInner)->FHashable();
}
示例#5
0
//---------------------------------------------------------------------------
//	@function:
//		CPartitionPropagationSpec::PdrgpexprPredicatesOnKey
//
//	@doc:
//		Returns an array of predicates on the given partitioning key given
//		an array of predicates on all keys
//
//---------------------------------------------------------------------------
DrgPexpr *
CPartitionPropagationSpec::PdrgpexprPredicatesOnKey
	(
	IMemoryPool *pmp,
	DrgPexpr *pdrgpexpr,
	CColRef *pcr,
	CColRefSet *pcrsKeys,
	CBitSet **ppbs
	)
{
	GPOS_ASSERT(NULL != pdrgpexpr);
	GPOS_ASSERT(NULL != pcr);
	GPOS_ASSERT(NULL != ppbs);
	GPOS_ASSERT(NULL != *ppbs);

	DrgPexpr *pdrgpexprResult = GPOS_NEW(pmp) DrgPexpr(pmp);

	const ULONG ulLen = pdrgpexpr->UlLength();
	for (ULONG ul = 0; ul < ulLen; ul++)
	{
		if ((*ppbs)->FBit(ul))
		{
			// this expression has already been added for another column
			continue;
		}

		CExpression *pexpr = (*pdrgpexpr)[ul];
		GPOS_ASSERT(pexpr->Pop()->FScalar());

		CColRefSet *pcrsUsed = CDrvdPropScalar::Pdpscalar(pexpr->PdpDerive())->PcrsUsed();
		CColRefSet *pcrsUsedKeys = GPOS_NEW(pmp) CColRefSet(pmp, *pcrsUsed);
		pcrsUsedKeys->Intersection(pcrsKeys);

		if (1 == pcrsUsedKeys->CElements() && pcrsUsedKeys->FMember(pcr))
		{
			pexpr->AddRef();
			pdrgpexprResult->Append(pexpr);
			(*ppbs)->FExchangeSet(ul);
		}

		pcrsUsedKeys->Release();
	}

	return pdrgpexprResult;
}
示例#6
0
//---------------------------------------------------------------------------
//	@function:
//		CExpressionHandle::PdrgpstatOuterRefs
//
//	@doc:
//		Given an array of stats objects and a child index, return an array
//		of stats objects starting from the first stats object referenced by
//		child
//
//---------------------------------------------------------------------------
DrgPstat *
CExpressionHandle::PdrgpstatOuterRefs
	(
	DrgPstat *pdrgpstat,
	ULONG ulChildIndex
	)
	const
{
	GPOS_ASSERT(NULL != pdrgpstat);
	GPOS_ASSERT(ulChildIndex < UlArity());

	if (FScalarChild(ulChildIndex) || !FHasOuterRefs(ulChildIndex))
	{
		// if child is scalar or has no outer references, return empty array
		return  GPOS_NEW(m_pmp) DrgPstat(m_pmp);
	}

	DrgPstat *pdrgpstatResult = GPOS_NEW(m_pmp) DrgPstat(m_pmp);
	CColRefSet *pcrsOuter = Pdprel(ulChildIndex)->PcrsOuter();
	GPOS_ASSERT(0 < pcrsOuter->CElements());

	const ULONG ulSize = pdrgpstat->UlLength();
	ULONG ulStartIndex = ULONG_MAX;
	for (ULONG ul = 0; ul < ulSize; ul++)
	{
		IStatistics *pstats = (*pdrgpstat)[ul];
		CColRefSet *pcrsStats = pstats->Pcrs(m_pmp);
		BOOL fStatsColsUsed = !pcrsOuter->FDisjoint(pcrsStats);
		pcrsStats->Release();
		if (fStatsColsUsed)
		{
			ulStartIndex = ul;
			break;
		}
	}

	if (ULONG_MAX != ulStartIndex)
	{
		// copy stats starting from index of outer-most stats object referenced by child
		CUtils::AddRefAppend<IStatistics, CleanupStats>(pdrgpstatResult, pdrgpstat, ulStartIndex);
	}

	return pdrgpstatResult;
}
示例#7
0
//---------------------------------------------------------------------------
//	@function:
//		CColumnFactory::AddComputedToUsedColsMap
//
//	@doc:
//		Add the map between computed column and its used columns
//
//---------------------------------------------------------------------------
void
CColumnFactory::AddComputedToUsedColsMap
	(
	CExpression *pexpr
	)
{
	GPOS_ASSERT(NULL != pexpr);
	GPOS_ASSERT(NULL != m_phmcrcrs);

	const CScalarProjectElement *popScPrEl = CScalarProjectElement::PopConvert(pexpr->Pop());
	CColRef *pcrComputedCol = popScPrEl->Pcr();

	CDrvdPropScalar *pdpscalar = CDrvdPropScalar::Pdpscalar(pexpr->PdpDerive());
	CColRefSet *pcrsUsed = pdpscalar->PcrsUsed();
	if (NULL != pcrsUsed && 0 < pcrsUsed->CElements())
	{
#ifdef GPOS_DEBUG
		BOOL fres =
#endif // GPOS_DEBUG
			m_phmcrcrs->FInsert(pcrComputedCol, GPOS_NEW(m_pmp) CColRefSet(m_pmp, *pcrsUsed));
		GPOS_ASSERT(fres);
	}
}
示例#8
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;
}
示例#9
0
//---------------------------------------------------------------------------
//	@function:
//		CConstraint::PcnstrFromScalarExpr
//
//	@doc:
//		Create constraint from scalar expression and pass back any discovered
//		equivalence classes
//
//---------------------------------------------------------------------------
CConstraint *
CConstraint::PcnstrFromScalarExpr
(
    IMemoryPool *pmp,
    CExpression *pexpr,
    DrgPcrs **ppdrgpcrs // output equivalence classes
)
{
    GPOS_ASSERT(NULL != pexpr);
    GPOS_ASSERT(pexpr->Pop()->FScalar());
    GPOS_ASSERT(NULL != ppdrgpcrs);
    GPOS_ASSERT(NULL == *ppdrgpcrs);

    (void) pexpr->PdpDerive();
    CDrvdPropScalar *pdpScalar = CDrvdPropScalar::Pdpscalar(pexpr->Pdp(CDrvdProp::EptScalar));

    CColRefSet *pcrs = pdpScalar->PcrsUsed();
    ULONG ulCols = pcrs->CElements();

    if (0 == ulCols)
    {
        // TODO:  - May 29, 2012: in case of an expr with no columns (e.g. 1 < 2),
        // possibly evaluate the expression, and return a "TRUE" or "FALSE" constraint
        return NULL;
    }

    if (1 == ulCols)
    {
        CColRef *pcr = pcrs->PcrFirst();
        if (!CUtils::FConstrainableType(pcr->Pmdtype()->Pmdid()))
        {
            return NULL;
        }

        CConstraint *pcnstr = NULL;
        *ppdrgpcrs = GPOS_NEW(pmp) DrgPcrs(pmp);

        // first, try creating a single interval constraint from the expression
        pcnstr = CConstraintInterval::PciIntervalFromScalarExpr(pmp, pexpr, pcr);
        if (NULL == pcnstr && CUtils::FScalarArrayCmp(pexpr))
        {
            // if the interval creation failed, try creating a disjunction or conjunction
            // of several interval constraints in the array case
            pcnstr = PcnstrFromScalarArrayCmp(pmp, pexpr, pcr);
        }

        if (NULL != pcnstr)
        {
            AddColumnToEquivClasses(pmp, pcr, ppdrgpcrs);
        }
        return pcnstr;
    }

    switch (pexpr->Pop()->Eopid())
    {
    case COperator::EopScalarBoolOp:
        return PcnstrFromScalarBoolOp(pmp, pexpr, ppdrgpcrs);

    case COperator::EopScalarCmp:
        return PcnstrFromScalarCmp(pmp, pexpr, ppdrgpcrs);

    default:
        return NULL;
    }
}
示例#10
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);
}
示例#11
0
//---------------------------------------------------------------------------
//	@function:
//		CColRefSetIterTest::EresUnittest_Basics
//
//	@doc:
//		Testing ctors/dtor; and pcr decoding;
//		Other functionality already tested in vanilla CBitSetIter;
//
//---------------------------------------------------------------------------
GPOS_RESULT
CColRefSetIterTest::EresUnittest_Basics()
{
	CAutoMemoryPool amp;
	IMemoryPool *pmp = amp.Pmp();

	// Setup an MD cache with a file-based provider
	CMDProviderMemory *pmdp = CTestUtils::m_pmdpf;
	pmdp->AddRef();
	CMDAccessor mda(pmp, CMDCache::Pcache());
	mda.RegisterProvider(CTestUtils::m_sysidDefault, pmdp);

	// install opt context in TLS
	CAutoOptCtxt aoc
				(
				pmp,
				&mda,
				NULL /* pceeval */,
				CTestUtils::Pcm(pmp)
				);

	// get column factory from optimizer context object
	CColumnFactory *pcf = COptCtxt::PoctxtFromTLS()->Pcf();

	CColRefSet *pcrs = GPOS_NEW(pmp) CColRefSet(pmp);
	CWStringConst strName(GPOS_WSZ_LIT("Test Column"));
	CName name(&strName);

	// create a int4 datum
	const IMDTypeInt4 *pmdtypeint4 = mda.PtMDType<IMDTypeInt4>();


	ULONG ulCols = 10;
	for(ULONG i = 0; i < ulCols; i++)
	{
		CColRef *pcr = pcf->PcrCreate(pmdtypeint4, name);
		pcrs->Include(pcr);

		GPOS_ASSERT(pcrs->FMember(pcr));
	}

	GPOS_ASSERT(pcrs->CElements() == ulCols);

	ULONG ulCount = 0;
	CColRefSetIter crsi(*pcrs);
	while(crsi.FAdvance())
	{
		GPOS_ASSERT((BOOL)crsi);

		CColRef *pcr = crsi.Pcr();
		GPOS_ASSERT(pcr->Name().FEquals(name));

		// to avoid unused variable warnings
		(void) pcr->UlId();

		ulCount++;
	}

	GPOS_ASSERT(ulCols == ulCount);
	GPOS_ASSERT(!((BOOL)crsi));

	pcrs->Release();

	return GPOS_OK;
}