Esempio n. 1
0
//---------------------------------------------------------------------------
//	@function:
//		CLogical::PcrsDeriveOuterIndexGet
//
//	@doc:
//		Derive outer references for index get and dynamic index get operators
//
//---------------------------------------------------------------------------
CColRefSet *
CLogical::PcrsDeriveOuterIndexGet
	(
	IMemoryPool *pmp,
	CExpressionHandle &exprhdl
	)
{
	ULONG ulArity = exprhdl.UlArity();
	CColRefSet *pcrsOuter = GPOS_NEW(pmp) CColRefSet(pmp);

	CColRefSet *pcrsOutput = PcrsDeriveOutput(pmp, exprhdl);
	
	CColRefSet *pcrsUsed = GPOS_NEW(pmp) CColRefSet(pmp);
	for (ULONG i = 0; i < ulArity; i++)
	{
		GPOS_ASSERT(exprhdl.FScalarChild(i));
		CDrvdPropScalar *pdpscalar = exprhdl.Pdpscalar(i);
		pcrsUsed->Union(pdpscalar->PcrsUsed());
	}

	// outer references are columns used by scalar children
	// but are not included in the output columns of relational children
	pcrsOuter->Union(pcrsUsed);
	pcrsOuter->Exclude(pcrsOutput);

	pcrsOutput->Release();
	pcrsUsed->Release();
	return pcrsOuter;
}
Esempio n. 2
0
//---------------------------------------------------------------------------
//	@function:
//		CLogical::PcrsDeriveOuter
//
//	@doc:
//		Derive outer references
//
//---------------------------------------------------------------------------
CColRefSet *
CLogical::PcrsDeriveOuter
	(
	IMemoryPool *pmp,
	CExpressionHandle &exprhdl,
	CColRefSet *pcrsUsedAdditional
	)
{
	ULONG ulArity = exprhdl.UlArity();
	CColRefSet *pcrsOuter = GPOS_NEW(pmp) CColRefSet(pmp);

	// collect output columns from relational children
	// and used columns from scalar children
	CColRefSet *pcrsOutput = GPOS_NEW(pmp) CColRefSet(pmp);

	CColRefSet *pcrsUsed = GPOS_NEW(pmp) CColRefSet(pmp);
	for (ULONG i = 0; i < ulArity; i++)
	{
		if (exprhdl.FScalarChild(i))
		{
			CDrvdPropScalar *pdpscalar = exprhdl.Pdpscalar(i);
			pcrsUsed->Union(pdpscalar->PcrsUsed());
		}
		else
		{
			CDrvdPropRelational *pdprel = exprhdl.Pdprel(i);
			pcrsOutput->Union(pdprel->PcrsOutput());

			// add outer references from relational children
			pcrsOuter->Union(pdprel->PcrsOuter());
		}
	}

	if (NULL != pcrsUsedAdditional)
	{
		pcrsUsed->Include(pcrsUsedAdditional);
	}

	// outer references are columns used by scalar child
	// but are not included in the output columns of relational children
	pcrsOuter->Union(pcrsUsed);
	pcrsOuter->Exclude(pcrsOutput);

	pcrsOutput->Release();
	pcrsUsed->Release();
	return pcrsOuter;
}
//---------------------------------------------------------------------------
//	@function:
//		CPhysicalComputeScalar::PrsDerive
//
//	@doc:
//		Derive rewindability
//
//---------------------------------------------------------------------------
CRewindabilitySpec *
CPhysicalComputeScalar::PrsDerive
	(
	IMemoryPool *pmp,
	CExpressionHandle &exprhdl
	)
	const
{
	CDrvdPropScalar *pdpscalar = exprhdl.Pdpscalar(1 /*ulChildIndex*/);
	if (pdpscalar->FHasNonScalarFunction() || IMDFunction::EfsVolatile == pdpscalar->Pfp()->Efs())
	{
		// ComputeScalar is not rewindable if it has non-scalar/volatile functions in project list
		return GPOS_NEW(pmp) CRewindabilitySpec(CRewindabilitySpec::ErtNone /*ert*/);
	}

	return PrsDerivePassThruOuter(exprhdl);
}
//---------------------------------------------------------------------------
//	@function:
//		CConstExprEvaluatorDXL::FValidInput
//
//	@doc:
//		Checks if the given expression is a valid input for constant expression evaluation,
//		i.e., a scalar expression without variables and without subqueries.
//		If it returns false, it sets the contents of the error message appropriately.
//		If szErrorMsg is not null and this function returns false, szErrorMsg will contain
//		the error message.
//
//---------------------------------------------------------------------------
BOOL
CConstExprEvaluatorDXL::FValidInput
	(
	CExpression *pexpr,
	const CHAR **szErrorMsg
	)
{
	GPOS_ASSERT(NULL != pexpr);
	// if the expression is not scalar, we should not try to evaluate it
	if (!pexpr->Pop()->FScalar())
	{
		if (NULL != szErrorMsg)
		{
			*szErrorMsg = pexpr->Pop()->SzId();
		}
		return false;
	}
	// if the expression has a subquery, we should not try to evaluate it
	if (CDrvdPropScalar::Pdpscalar(pexpr->PdpDerive())->FHasSubquery())
	{
		if (NULL != szErrorMsg)
		{
			*szErrorMsg = "expression containing subqueries";
		}
		return false;
	}
	// if the expression uses or defines any variables, we should not try to evaluate it
	CDrvdPropScalar *pdpScalar = CDrvdPropScalar::Pdpscalar(pexpr->PdpDerive());
	if (0 != pdpScalar->PcrsUsed()->CElements() ||
		0 != pdpScalar->PcrsDefined()->CElements())
	{
		if (NULL != szErrorMsg)
		{
			*szErrorMsg = "expression with variables";
		}
		return false;
	}
	return true;
}
Esempio n. 5
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::GetDrvdScalarProps(pexpr->PdpDerive());
	CColRefSet *pcrsUsed = pdpscalar->PcrsUsed();
	if (NULL != pcrsUsed && 0 < pcrsUsed->Size())
	{
#ifdef GPOS_DEBUG
		BOOL fres =
#endif // GPOS_DEBUG
			m_phmcrcrs->Insert(pcrComputedCol, GPOS_NEW(m_mp) CColRefSet(m_mp, *pcrsUsed));
		GPOS_ASSERT(fres);
	}
}
Esempio n. 6
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;
    }
}
//---------------------------------------------------------------------------
//	@function:
//		CPhysicalComputeScalar::PdsRequired
//
//	@doc:
//		Compute required distribution of the n-th child
//
//---------------------------------------------------------------------------
CDistributionSpec *
CPhysicalComputeScalar::PdsRequired
	(
	IMemoryPool *pmp,
	CExpressionHandle &exprhdl,
	CDistributionSpec *pdsRequired,
	ULONG ulChildIndex,
	DrgPdp *, // pdrgpdpCtxt
	ULONG ulOptReq
	)
	const
{
	GPOS_ASSERT(0 == ulChildIndex);
	GPOS_ASSERT(2 > ulOptReq);

	// check if master-only/replicated distribution needs to be requested
	CDistributionSpec *pds = PdsMasterOnlyOrReplicated(pmp, exprhdl, pdsRequired, ulChildIndex, ulOptReq);
	if (NULL != pds)
	{
		return pds;
	}

	CDrvdPropScalar *pdpscalar = exprhdl.Pdpscalar(1 /*ulChildIndex*/);

	// if a Project operator has a call to a set function, passing a Random distribution through this
	// Project may have the effect of not distributing the results of the set function to all nodes,
	// but only to the nodes on which first child of the Project is distributed.
	// to avoid that, we don't push the distribution requirement in this case and thus, for a random
	// distribution, the result of the set function is spread uniformly over all nodes
	if (pdpscalar->FHasNonScalarFunction())
	{
		return GPOS_NEW(pmp) CDistributionSpecAny();
	}

	// if required distribution uses any defined column, it has to be enforced on top of ComputeScalar,
	// in this case, we request Any distribution from the child
	CDistributionSpec::EDistributionType edtRequired = pdsRequired->Edt();
	if (CDistributionSpec::EdtHashed == edtRequired)
	{
		CDistributionSpecHashed *pdshashed = CDistributionSpecHashed::PdsConvert(pdsRequired);
		CColRefSet *pcrs = pdshashed->PcrsUsed(m_pmp);
		BOOL fUsesDefinedCols = FUnaryUsesDefinedColumns(pcrs, exprhdl);
		pcrs->Release();
		if (fUsesDefinedCols)
		{
			return GPOS_NEW(pmp) CDistributionSpecAny();
		}
	}

	if (CDistributionSpec::EdtRouted == edtRequired)
	{
		CDistributionSpecRouted *pdsrouted = CDistributionSpecRouted::PdsConvert(pdsRequired);
		CColRefSet *pcrs = GPOS_NEW(m_pmp) CColRefSet(m_pmp);
		pcrs->Include(pdsrouted->Pcr());
		BOOL fUsesDefinedCols = FUnaryUsesDefinedColumns(pcrs, exprhdl);
		pcrs->Release();
		if (fUsesDefinedCols)
		{
			return GPOS_NEW(pmp) CDistributionSpecAny();
		}
	}

	if (0 == ulOptReq)
	{
		// Req0: required distribution will be enforced on top of ComputeScalar
		return GPOS_NEW(pmp) CDistributionSpecAny();
	}

	// Req1: required distribution will be enforced on top of ComputeScalar's child
	return PdsPassThru(pmp, exprhdl, pdsRequired, ulChildIndex);
}
//---------------------------------------------------------------------------
//	@function:
//		CLogicalDynamicGetBase::PstatsDeriveFilter
//
//	@doc:
//		Derive stats from base table using filters on partition and/or index columns
//
//---------------------------------------------------------------------------
IStatistics *
CLogicalDynamicGetBase::PstatsDeriveFilter
	(
	IMemoryPool *pmp,
	CExpressionHandle &exprhdl,
	CExpression *pexprFilter
	)
	const
{
	CExpression *pexprFilterNew = NULL;
	CConstraint *pcnstr = m_ppartcnstr->PcnstrCombined();
	if (m_fPartial && NULL != pcnstr && !pcnstr->FUnbounded())
	{
		if (NULL == pexprFilter)
		{
			pexprFilterNew = pcnstr->PexprScalar(pmp);
			pexprFilterNew->AddRef();
		}
		else
		{
			pexprFilterNew = CPredicateUtils::PexprConjunction(pmp, pexprFilter, pcnstr->PexprScalar(pmp));
		}
	}
	else if (NULL != pexprFilter)
	{
		pexprFilterNew = pexprFilter;
		pexprFilterNew->AddRef();
	}

	CColRefSet *pcrsStat = GPOS_NEW(pmp) CColRefSet(pmp);
	CDrvdPropScalar *pdpscalar = NULL;

	if (NULL != pexprFilterNew)
	{
		pdpscalar = CDrvdPropScalar::Pdpscalar(pexprFilterNew->PdpDerive());
		pcrsStat->Include(pdpscalar->PcrsUsed());
	}

	// requesting statistics on distribution columns to estimate data skew
	if (NULL != m_pcrsDist)
	{
		pcrsStat->Include(m_pcrsDist);
	}


	IStatistics *pstatsFullTable = PstatsBaseTable(pmp, exprhdl, m_ptabdesc, pcrsStat);
	
	pcrsStat->Release();
	
	if (NULL == pexprFilterNew || pdpscalar->FHasSubquery())
	{
		return pstatsFullTable;
	}

	CStatsPred *pstatspred =  CStatsPredUtils::PstatspredExtract
												(
												pmp, 
												pexprFilterNew, 
												NULL /*pcrsOuterRefs*/
												);
	pexprFilterNew->Release();

	IStatistics *pstatsResult = pstatsFullTable->PstatsFilter
													(
													pmp, 
													pstatspred, 
													true /* fCapNdvs */ 
													);
	pstatspred->Release();
	pstatsFullTable->Release();

	return pstatsResult;
}