//--------------------------------------------------------------------------- // @function: // CPhysicalUnionAll::AssertValidChildDistributions // // @doc: // Helper to validate child distributions // //--------------------------------------------------------------------------- void CPhysicalUnionAll::AssertValidChildDistributions ( IMemoryPool *pmp, CExpressionHandle &exprhdl, CDistributionSpec::EDistributionType *pedt, // array of distribution types to check ULONG ulDistrs, // number of distribution types to check const CHAR *szAssertMsg ) { const ULONG ulArity = exprhdl.UlArity(); for (ULONG ulChild = 0; ulChild < ulArity; ulChild++) { CDistributionSpec *pdsChild = exprhdl.Pdpplan(ulChild)->Pds(); CDistributionSpec::EDistributionType edtChild = pdsChild->Edt(); BOOL fMatch = false; for (ULONG ulDistr = 0; !fMatch && ulDistr < ulDistrs; ulDistr++) { fMatch = (pedt[ulDistr] == edtChild); } if (!fMatch) { CAutoTrace at(pmp); at.Os() << szAssertMsg; } GPOS_ASSERT(fMatch); } }
//--------------------------------------------------------------------------- // @function: // CPhysicalAgg::EpetDistribution // // @doc: // Return the enforcing type for distribution property based on this operator // //--------------------------------------------------------------------------- CEnfdProp::EPropEnforcingType CPhysicalAgg::EpetDistribution ( CExpressionHandle &exprhdl, const CEnfdDistribution *ped ) const { GPOS_ASSERT(NULL != ped); // get distribution delivered by the aggregate node CDistributionSpec *pds = CDrvdPropPlan::Pdpplan(exprhdl.Pdp())->Pds(); if (ped->FCompatible(pds)) { if (COperator::EgbaggtypeLocal != Egbaggtype()) { return CEnfdProp::EpetUnnecessary; } // prohibit the plan if local aggregate already delivers the enforced distribution, since // otherwise we would create two aggregates with no intermediate motion operators return CEnfdProp::EpetProhibited; } // if there are outer refs, we cannot have a motion on top if (exprhdl.FHasOuterRefs()) { return CEnfdProp::EpetProhibited; } // required distribution will be enforced on Agg's output return CEnfdProp::EpetRequired; }
//--------------------------------------------------------------------------- // @function: // CPhysicalPartitionSelectorDML::EpetDistribution // // @doc: // Return the enforcing type for distribution property based on this operator // //--------------------------------------------------------------------------- CEnfdProp::EPropEnforcingType CPhysicalPartitionSelectorDML::EpetDistribution ( CExpressionHandle &exprhdl, const CEnfdDistribution *ped ) const { GPOS_ASSERT(NULL != ped); // get distribution delivered by the filter node CDistributionSpec *pds = CDrvdPropPlan::Pdpplan(exprhdl.Pdp())->Pds(); if (ped->FCompatible(pds)) { // required distribution is already provided return CEnfdProp::EpetUnnecessary; } if (exprhdl.HasOuterRefs()) { return CEnfdProp::EpetProhibited; } return CEnfdProp::EpetRequired; }
//--------------------------------------------------------------------------- // @function: // CPhysicalJoin::FProvidesReqdCols // // @doc: // Helper for checking if required columns are included in output columns // //--------------------------------------------------------------------------- BOOL CPhysicalJoin::FProvidesReqdCols ( CExpressionHandle &exprhdl, CColRefSet *pcrsRequired, ULONG // ulOptReq ) const { GPOS_ASSERT(NULL != pcrsRequired); GPOS_ASSERT(3 == exprhdl.UlArity()); // union columns from relational children CColRefSet *pcrs = GPOS_NEW(m_pmp) CColRefSet(m_pmp); ULONG ulArity = exprhdl.UlArity(); for (ULONG i = 0; i < ulArity - 1; i++) { CColRefSet *pcrsChild = exprhdl.Pdprel(i)->PcrsOutput(); pcrs->Union(pcrsChild); } BOOL fProvidesCols = pcrs->FSubset(pcrsRequired); pcrs->Release(); return fProvidesCols; }
//--------------------------------------------------------------------------- // @function: // CLogicalSequence::Maxcard // // @doc: // Derive max card // //--------------------------------------------------------------------------- CMaxCard CLogicalSequence::Maxcard ( IMemoryPool *, // mp CExpressionHandle &exprhdl ) const { // pass on max card of last child return exprhdl.GetRelationalProperties(exprhdl.Arity() - 1)->Maxcard(); }
//--------------------------------------------------------------------------- // @function: // CLogicalSequenceProject::FHasLocalOuterRefs // // @doc: // Return true if outer references are included in Partition/Order, // or window frame edges // //--------------------------------------------------------------------------- BOOL CLogicalSequenceProject::FHasLocalOuterRefs ( CExpressionHandle &exprhdl ) const { GPOS_ASSERT(this == exprhdl.Pop()); CColRefSet *outer_refs = CDrvdPropRelational::GetRelationalProperties(exprhdl.Pdp())->PcrsOuter(); return !(outer_refs->IsDisjoint(m_pcrsLocalUsed)); }
//--------------------------------------------------------------------------- // @function: // CPhysicalJoin::FOuterProvidesReqdCols // // @doc: // Helper for checking if the outer input of a binary join operator // includes the required columns // //--------------------------------------------------------------------------- BOOL CPhysicalJoin::FOuterProvidesReqdCols ( CExpressionHandle &exprhdl, CColRefSet *pcrsRequired ) { GPOS_ASSERT(NULL != pcrsRequired); GPOS_ASSERT(3 == exprhdl.UlArity() && "expected binary join"); CColRefSet *pcrsOutput = exprhdl.Pdprel(0 /*ulChildIndex*/)->PcrsOutput(); return pcrsOutput->FSubset(pcrsRequired); }
//--------------------------------------------------------------------------- // @function: // CXformSubqJoin2Apply::Exfp // // @doc: // Compute xform promise for a given expression handle; // if subqueries exist in the scalar predicate, we must have an // equivalent logical Apply expression created during exploration; // no need for generating a Join expression here // //--------------------------------------------------------------------------- CXform::EXformPromise CXformSubqJoin2Apply::Exfp ( CExpressionHandle &exprhdl ) const { if (exprhdl.GetDrvdScalarProps(exprhdl.Arity() - 1)->FHasSubquery()) { return CXform::ExfpHigh; } return CXform::ExfpNone; }
//--------------------------------------------------------------------------- // @function: // CXformGbAgg2Apply::Exfp // // @doc: // Compute xform promise for a given expression handle; // scalar child must have subquery // //--------------------------------------------------------------------------- CXform::EXformPromise CXformGbAgg2Apply::Exfp ( CExpressionHandle &exprhdl ) const { CLogicalGbAgg *popGbAgg = CLogicalGbAgg::PopConvert(exprhdl.Pop()); if (popGbAgg->FGlobal() && exprhdl.Pdpscalar(1)->FHasSubquery()) { return CXform::ExfpHigh; } return CXform::ExfpNone; }
//--------------------------------------------------------------------------- // @function: // CPhysicalUnionAll::FProvidesReqdCols // // @doc: // Check if required columns are included in output columns // //--------------------------------------------------------------------------- BOOL CPhysicalUnionAll::FProvidesReqdCols ( CExpressionHandle & #ifdef GPOS_DEBUG exprhdl #endif // GPOS_DEBUG , CColRefSet *pcrsRequired, ULONG // ulOptReq ) const { GPOS_ASSERT(NULL != pcrsRequired); GPOS_ASSERT(m_pdrgpdrgpcrInput->UlLength() == exprhdl.UlArity()); CColRefSet *pcrs = GPOS_NEW(m_pmp) CColRefSet(m_pmp); // include output columns pcrs->Include(m_pdrgpcrOutput); BOOL fProvidesCols = pcrs->FSubset(pcrsRequired); pcrs->Release(); return fProvidesCols; }
void CDistributionSpecHashedNoOp::AppendEnforcers ( IMemoryPool *pmp, CExpressionHandle &exprhdl, CReqdPropPlan *, DrgPexpr *pdrgpexpr, CExpression *pexpr ) { CDrvdProp *pdp = exprhdl.Pdp(); CDistributionSpec *pdsChild = CDrvdPropPlan::Pdpplan(pdp)->Pds(); CDistributionSpecHashed *pdsChildHashed = dynamic_cast<CDistributionSpecHashed *>(pdsChild); if (NULL == pdsChildHashed) { return; } DrgPexpr *pdrgpexprNoOpRedistributionColumns = pdsChildHashed->Pdrgpexpr(); pdrgpexprNoOpRedistributionColumns->AddRef(); CDistributionSpecHashedNoOp* pdsNoOp = GPOS_NEW(pmp) CDistributionSpecHashedNoOp(pdrgpexprNoOpRedistributionColumns); pexpr->AddRef(); CExpression *pexprMotion = GPOS_NEW(pmp) CExpression ( pmp, GPOS_NEW(pmp) CPhysicalMotionHashDistribute(pmp, pdsNoOp), pexpr ); pdrgpexpr->Append(pexprMotion); }
//--------------------------------------------------------------------------- // @function: // CPhysicalPartitionSelectorDML::EpetOrder // // @doc: // Return the enforcing type for order property based on this operator // //--------------------------------------------------------------------------- CEnfdProp::EPropEnforcingType CPhysicalPartitionSelectorDML::EpetOrder ( CExpressionHandle &exprhdl, const CEnfdOrder *peo ) const { GPOS_ASSERT(NULL != peo); GPOS_ASSERT(!peo->PosRequired()->IsEmpty()); COrderSpec *pos = CDrvdPropPlan::Pdpplan(exprhdl.Pdp())->Pos(); if (peo->FCompatible(pos)) { return CEnfdProp::EpetUnnecessary; } // Sort has to go above if sort columns use any column // defined here, otherwise, Sort can either go above or below CColRefSet *pcrsSort = peo->PosRequired()->PcrsUsed(m_mp); BOOL fUsesDefinedCols = pcrsSort->FMember(m_pcrOid); pcrsSort->Release(); if (fUsesDefinedCols) { return CEnfdProp::EpetRequired; } return CEnfdProp::EpetOptional; }
//--------------------------------------------------------------------------- // @function: // CPhysicalComputeScalar::EpetOrder // // @doc: // Return the enforcing type for order property based on this operator // //--------------------------------------------------------------------------- CEnfdProp::EPropEnforcingType CPhysicalComputeScalar::EpetOrder ( CExpressionHandle &exprhdl, const CEnfdOrder *peo ) const { GPOS_ASSERT(NULL != peo); GPOS_ASSERT(!peo->PosRequired()->FEmpty()); COrderSpec *pos = CDrvdPropPlan::Pdpplan(exprhdl.Pdp())->Pos(); if (peo->FCompatible(pos)) { return CEnfdProp::EpetUnnecessary; } // Sort has to go above ComputeScalar if sort columns use any column // defined by ComputeScalar, otherwise, Sort can either go above or below ComputeScalar CColRefSet *pcrsSort = peo->PosRequired()->PcrsUsed(m_pmp); BOOL fUsesDefinedCols = FUnaryUsesDefinedColumns(pcrsSort, exprhdl); pcrsSort->Release(); if (fUsesDefinedCols) { return CEnfdProp::EpetRequired; } return CEnfdProp::EpetOptional; }
//--------------------------------------------------------------------------- // @function: // CXformInnerApplyWithOuterKey2InnerJoin::Exfp // // @doc: // Compute xform promise for a given expression handle; // //--------------------------------------------------------------------------- CXform::EXformPromise CXformInnerApplyWithOuterKey2InnerJoin::Exfp ( CExpressionHandle &exprhdl ) const { // check if outer child has key and inner child has outer references if (NULL == exprhdl.Pdprel(0)->Pkc() || 0 == exprhdl.Pdprel(1)->PcrsOuter()->CElements()) { return ExfpNone; } return ExfpHigh; }
//--------------------------------------------------------------------------- // @function: // CDrvdPropPlan::Derive // // @doc: // Derive plan props // //--------------------------------------------------------------------------- void CDrvdPropPlan::Derive ( IMemoryPool *pmp, CExpressionHandle &exprhdl, CDrvdPropCtxt *pdpctxt ) { CPhysical *popPhysical = CPhysical::PopConvert(exprhdl.Pop()); if (NULL != pdpctxt && COperator::EopPhysicalCTEConsumer == popPhysical->Eopid()) { CopyCTEProducerPlanProps(pmp, pdpctxt, popPhysical); } else { // call property derivation functions on the operator m_pos = popPhysical->PosDerive(pmp, exprhdl); m_pds = popPhysical->PdsDerive(pmp, exprhdl); m_prs = popPhysical->PrsDerive(pmp, exprhdl); m_ppim = popPhysical->PpimDerive(pmp, exprhdl, pdpctxt); m_ppfm = popPhysical->PpfmDerive(pmp, exprhdl); GPOS_ASSERT(NULL != m_ppim); GPOS_ASSERT(CDistributionSpec::EdtAny != m_pds->Edt() && "CDistributionAny is a require-only, cannot be derived"); } m_pcm = popPhysical->PcmDerive(pmp, exprhdl); }
//--------------------------------------------------------------------------- // @function: // CLogicalDifferenceAll::Maxcard // // @doc: // Derive max card // //--------------------------------------------------------------------------- CMaxCard CLogicalDifferenceAll::Maxcard ( IMemoryPool *, // pmp CExpressionHandle &exprhdl ) const { // contradictions produce no rows if (CDrvdPropRelational::Pdprel(exprhdl.Pdp())->Ppc()->FContradiction()) { return CMaxCard(0 /*ull*/); } return exprhdl.Pdprel(0)->Maxcard(); }
//--------------------------------------------------------------------------- // @function: // CPhysicalPartitionSelector::EpetDistribution // // @doc: // Return the enforcing type for distribution property based on this operator // //--------------------------------------------------------------------------- CEnfdProp::EPropEnforcingType CPhysicalPartitionSelector::EpetDistribution ( CExpressionHandle &exprhdl, const CEnfdDistribution *ped ) const { CDrvdPropPlan *pdpplan = exprhdl.Pdpplan(0 /* child_index */); if (ped->FCompatible(pdpplan->Pds())) { // required distribution established by the operator return CEnfdProp::EpetUnnecessary; } CPartIndexMap *ppimDrvd = pdpplan->Ppim(); if (!ppimDrvd->Contains(m_scan_id)) { // part consumer is defined above: prohibit adding a motion on top of the // part resolver as this will create two slices return CEnfdProp::EpetProhibited; } GPOS_ASSERT(CPartIndexMap::EpimConsumer == ppimDrvd->Epim(m_scan_id)); // part consumer found below: enforce distribution on top of part resolver return CEnfdProp::EpetRequired; }
//--------------------------------------------------------------------------- // @function: // CPhysical::FUnaryUsesDefinedColumns // // @doc: // Return true if the given column set includes any of the columns defined // by the unary node, as given by the handle // //--------------------------------------------------------------------------- BOOL CPhysical::FUnaryUsesDefinedColumns ( CColRefSet *pcrs, CExpressionHandle &exprhdl ) { GPOS_ASSERT(NULL != pcrs); GPOS_ASSERT(2 == exprhdl.Arity() && "Not a unary operator"); if (0 == pcrs->Size()) { return false; } return !pcrs->IsDisjoint(exprhdl.GetDrvdScalarProps(1)->PcrsDefined()); }
//--------------------------------------------------------------------------- // @function: // CLogicalUnion::Maxcard // // @doc: // Derive max card // //--------------------------------------------------------------------------- CMaxCard CLogicalUnion::Maxcard ( IMemoryPool *, // mp CExpressionHandle &exprhdl ) const { const ULONG arity = exprhdl.Arity(); CMaxCard maxcard = exprhdl.GetRelationalProperties(0)->Maxcard(); for (ULONG ul = 1; ul < arity; ul++) { maxcard += exprhdl.GetRelationalProperties(ul)->Maxcard(); } return maxcard; }
//--------------------------------------------------------------------------- // @function: // CLogicalUnion::Maxcard // // @doc: // Derive max card // //--------------------------------------------------------------------------- CMaxCard CLogicalUnion::Maxcard ( IMemoryPool *, // pmp CExpressionHandle &exprhdl ) const { const ULONG ulArity = exprhdl.UlArity(); CMaxCard maxcard = exprhdl.Pdprel(0)->Maxcard(); for (ULONG ul = 1; ul < ulArity; ul++) { maxcard += exprhdl.Pdprel(ul)->Maxcard(); } return maxcard; }
//--------------------------------------------------------------------------- // @function: // CPhysical::FChildrenHaveCompatibleDistributions // // @doc: // Returns true iff the delivered distributions of the children are // compatible among themselves. // //--------------------------------------------------------------------------- BOOL CPhysical::FCompatibleChildrenDistributions ( const CExpressionHandle &exprhdl ) const { GPOS_ASSERT(exprhdl.Pop() == this); BOOL fSingletonOrUniversalChild = false; BOOL fNotSingletonOrUniversalDistributedChild = false; const ULONG arity = exprhdl.Arity(); for (ULONG ul = 0; ul < arity; ul++) { if (!exprhdl.FScalarChild(ul)) { CDrvdPropPlan *pdpplanChild = exprhdl.Pdpplan(ul); // an operator cannot have a singleton or universal distributed child // and one distributed on multiple nodes // this assumption is safe for all current operators, but it can be // too conservative: we could allow for instance the following cases // * LeftOuterJoin (universal, distributed) // * AntiSemiJoin (universal, distributed) // These cases can be enabled if considered necessary by overriding // this function. if (CDistributionSpec::EdtUniversal == pdpplanChild->Pds()->Edt() || pdpplanChild->Pds()->FSingletonOrStrictSingleton()) { fSingletonOrUniversalChild = true; } else { fNotSingletonOrUniversalDistributedChild = true; } if (fSingletonOrUniversalChild && fNotSingletonOrUniversalDistributedChild) { return false; } } } return true; }
//--------------------------------------------------------------------------- // @function: // CPhysicalSequence::FProvidesReqdCols // // @doc: // Helper for checking if required columns are included in output columns // //--------------------------------------------------------------------------- BOOL CPhysicalSequence::FProvidesReqdCols ( CExpressionHandle &exprhdl, CColRefSet *pcrsRequired, ULONG // ulOptReq ) const { GPOS_ASSERT(NULL != pcrsRequired); // last child must provide required columns ULONG ulArity = exprhdl.UlArity(); GPOS_ASSERT(0 < ulArity); CColRefSet *pcrsChild = exprhdl.Pdprel(ulArity - 1)->PcrsOutput(); return pcrsChild->FSubset(pcrsRequired); }
//--------------------------------------------------------------------------- // @function: // CLogicalLeftSemiApply::Maxcard // // @doc: // Derive max card // //--------------------------------------------------------------------------- CMaxCard CLogicalLeftSemiApply::Maxcard ( IMemoryPool *, // mp CExpressionHandle &exprhdl ) const { return CLogical::Maxcard(exprhdl, 2 /*ulScalarIndex*/, exprhdl.GetRelationalProperties(0)->Maxcard()); }
//--------------------------------------------------------------------------- // @function: // CXformGbAgg2StreamAgg::Exfp // // @doc: // Compute xform promise for a given expression handle; // grouping columns must be non-empty // //--------------------------------------------------------------------------- CXform::EXformPromise CXformGbAgg2StreamAgg::Exfp ( CExpressionHandle &exprhdl ) const { CLogicalGbAgg *popAgg = CLogicalGbAgg::PopConvert(exprhdl.Pop()); if (0 == popAgg->Pdrgpcr()->UlLength() || !CUtils::FComparisonPossible(popAgg->Pdrgpcr(), IMDType::EcmptL) || exprhdl.Pdpscalar(1 /*ulChildIndex*/)->FHasSubquery()) { // no grouping columns, or no sort operators are available for grouping columns, or // agg functions use subquery arguments return CXform::ExfpNone; } return CXform::ExfpHigh; }
//--------------------------------------------------------------------------- // @function: // CLogicalLeftSemiApply::Maxcard // // @doc: // Derive max card // //--------------------------------------------------------------------------- CMaxCard CLogicalLeftSemiApply::Maxcard ( IMemoryPool *, // pmp CExpressionHandle &exprhdl ) const { return CLogical::Maxcard(exprhdl, 2 /*ulScalarIndex*/, exprhdl.Pdprel(0)->Maxcard()); }
//--------------------------------------------------------------------------- // @function: // CLogicalSelect::Maxcard // // @doc: // Derive max card // //--------------------------------------------------------------------------- CMaxCard CLogicalSelect::Maxcard ( IMemoryPool *, // pmp CExpressionHandle &exprhdl ) const { // in case of a false condition or a contradiction, maxcard should be zero CExpression *pexprScalar = exprhdl.PexprScalarChild(1); if ((NULL != pexprScalar && CUtils::FScalarConstFalse(pexprScalar)) || CDrvdPropRelational::Pdprel(exprhdl.Pdp())->Ppc()->FContradiction()) { return CMaxCard(0 /*ull*/); } // pass on max card of first child return exprhdl.Pdprel(0)->Maxcard(); }
//--------------------------------------------------------------------------- // @function: // CLogical::MaxcardDef // // @doc: // Default max card for join and apply operators // //--------------------------------------------------------------------------- CMaxCard CLogical::MaxcardDef ( CExpressionHandle &exprhdl ) { const ULONG ulArity = exprhdl.UlArity(); CMaxCard maxcard = exprhdl.Pdprel(0)->Maxcard(); for (ULONG ul = 1; ul < ulArity - 1; ul++) { if (!exprhdl.FScalarChild(ul)) { maxcard *= exprhdl.Pdprel(ul)->Maxcard(); } } return maxcard; }
//--------------------------------------------------------------------------- // @function: // CXformGbAggWithMDQA2Join::Exfp // // @doc: // Compute xform promise for a given expression handle; // //--------------------------------------------------------------------------- CXform::EXformPromise CXformGbAggWithMDQA2Join::Exfp ( CExpressionHandle &exprhdl ) const { CAutoMemoryPool amp; CLogicalGbAgg *popAgg = CLogicalGbAgg::PopConvert(exprhdl.Pop()); if (COperator::EgbaggtypeGlobal == popAgg->Egbaggtype() && exprhdl.Pdpscalar(1 /*ulChildIndex*/)->FHasMultipleDistinctAggs()) { return CXform::ExfpHigh; } return CXform::ExfpNone; }
//--------------------------------------------------------------------------- // @function: // CLogicalCTEAnchor::Maxcard // // @doc: // Derive max card // //--------------------------------------------------------------------------- CMaxCard CLogicalCTEAnchor::Maxcard ( IMemoryPool *, // pmp CExpressionHandle &exprhdl ) const { // pass on max card of first child return exprhdl.Pdprel(0)->Maxcard(); }
//--------------------------------------------------------------------------- // @function: // CLogicalLimit::Maxcard // // @doc: // Derive max card // //--------------------------------------------------------------------------- CMaxCard CLogicalLimit::Maxcard ( IMemoryPool *, // pmp CExpressionHandle &exprhdl ) const { CExpression *pexprCount = exprhdl.PexprScalarChild(2 /*ulChildIndex*/); if (CUtils::FScalarConstInt<IMDTypeInt8>(pexprCount)) { CScalarConst *popScalarConst = CScalarConst::PopConvert(pexprCount->Pop()); IDatumInt8 *pdatumInt8 = dynamic_cast<IDatumInt8 *>(popScalarConst->Pdatum()); return CMaxCard(pdatumInt8->LValue()); } // pass on max card of first child return exprhdl.Pdprel(0)->Maxcard(); }