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];
		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;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
0
//---------------------------------------------------------------------------
//	@function:
//		CStatsPredUtils::ProcessArrayCmp
//
//	@doc:
//		Extract statistics filtering information from scalar array comparison
//---------------------------------------------------------------------------
void
CStatsPredUtils::ProcessArrayCmp
	(
	IMemoryPool *pmp,
	CExpression *pexprPred,
	DrgPstatspred *pdrgpstatspred
	)
{
	GPOS_ASSERT(NULL != pdrgpstatspred);
	GPOS_ASSERT(NULL != pexprPred);
	GPOS_ASSERT(2 == pexprPred->UlArity());

	CScalarArrayCmp *popScArrayCmp = CScalarArrayCmp::PopConvert(pexprPred->Pop());
	CExpression *pexprLeft = (*pexprPred)[0];
	CExpression *pexprRight = (*pexprPred)[1];

	BOOL fCompareToConst = ((COperator::EopScalarIdent == pexprLeft->Pop()->Eopid())
							&& (COperator::EopScalarArray == pexprRight->Pop()->Eopid()));

	if (!fCompareToConst)
	{
		// unsupported predicate for stats calculations
		pdrgpstatspred->Append(GPOS_NEW(pmp) CStatsPredUnsupported(ULONG_MAX, CStatsPred::EstatscmptOther));

		return;
	}

	BOOL fAny = (CScalarArrayCmp::EarrcmpAny == popScArrayCmp->Earrcmpt());

	DrgPstatspred *pdrgpstatspredChild = pdrgpstatspred;
	if (fAny)
	{
		pdrgpstatspredChild = GPOS_NEW(pmp) DrgPstatspred(pmp);
	}

	const ULONG ulConstants = pexprRight->UlArity();
	// comparison semantics for statistics purposes is looser than regular comparison.
	CStatsPred::EStatsCmpType escmpt = Estatscmptype(popScArrayCmp->PmdidOp());

	CScalarIdent *popScalarIdent = CScalarIdent::PopConvert(pexprLeft->Pop());
	const CColRef *pcr = popScalarIdent->Pcr();

	if (!CHistogram::FSupportsFilter(escmpt))
	{
		// unsupported predicate for stats calculations
		pdrgpstatspred->Append(GPOS_NEW(pmp) CStatsPredUnsupported(pcr->UlId(), escmpt));

		return;
	}

	for (ULONG ul = 0; ul < ulConstants; ul++)
	{
		CExpression *pexprConst = (*pexprRight)[ul];
		if (COperator::EopScalarConst == pexprConst->Pop()->Eopid())
		{
			CScalarConst *popScalarConst = CScalarConst::PopConvert(pexprConst->Pop());
			IDatum *pdatumLiteral = popScalarConst->Pdatum();
			CStatsPred *pstatspredChild = NULL;
			if (!pdatumLiteral->FStatsComparable(pdatumLiteral))
			{
				// stats calculations on such datums unsupported
				pstatspredChild = GPOS_NEW(pmp) CStatsPredUnsupported(pcr->UlId(), escmpt);
			}
			else
			{
				pstatspredChild = GPOS_NEW(pmp) CStatsPredPoint(pmp, pcr, escmpt, pdatumLiteral);
			}

			pdrgpstatspredChild->Append(pstatspredChild);
		}
	}

	if (fAny)
	{
		CStatsPredDisj *pstatspredOr = GPOS_NEW(pmp) CStatsPredDisj(pdrgpstatspredChild);
		pdrgpstatspred->Append(pstatspredOr);
	}
}