//--------------------------------------------------------------------------- // @function: // CLogical::PkcKeysBaseTable // // @doc: // Helper function for computing the keys in a base table // //--------------------------------------------------------------------------- CKeyCollection * CLogical::PkcKeysBaseTable ( IMemoryPool *pmp, const DrgPbs *pdrgpbsKeys, const DrgPcr *pdrgpcrOutput ) { const ULONG ulKeys = pdrgpbsKeys->UlLength(); if (0 == ulKeys) { return NULL; } CKeyCollection *pkc = GPOS_NEW(pmp) CKeyCollection(pmp); for (ULONG ul = 0; ul < ulKeys; ul++) { CColRefSet *pcrs = GPOS_NEW(pmp) CColRefSet(pmp); CBitSet *pbs = (*pdrgpbsKeys)[ul]; CBitSetIter bsiter(*pbs); while (bsiter.FAdvance()) { pcrs->Include((*pdrgpcrOutput)[bsiter.UlBit()]); } pkc->Add(pcrs); } return pkc; }
//--------------------------------------------------------------------------- // @function: // CLogical::PkcCombineKeys // // @doc: // Common case of combining keys from first n - 1 children // //--------------------------------------------------------------------------- CKeyCollection * CLogical::PkcCombineKeys ( IMemoryPool *pmp, CExpressionHandle &exprhdl ) { CColRefSet *pcrs = GPOS_NEW(pmp) CColRefSet(pmp); const ULONG ulArity = exprhdl.UlArity(); for (ULONG ul = 0; ul < ulArity - 1; ul++) { CKeyCollection *pkc = exprhdl.Pdprel(ul)->Pkc(); if (NULL == pkc) { // if a child has no key, the operator has no key pcrs->Release(); return NULL; } DrgPcr *pdrgpcr = pkc->PdrgpcrKey(pmp); pcrs->Include(pdrgpcr); pdrgpcr->Release(); } return GPOS_NEW(pmp) CKeyCollection(pmp, pcrs); }
//--------------------------------------------------------------------------- // @function: // CXformLeftSemiJoin2InnerJoin::Transform // // @doc: // actual transformation // //--------------------------------------------------------------------------- void CXformLeftSemiJoin2InnerJoin::Transform ( CXformContext *pxfctxt, CXformResult *pxfres, CExpression *pexpr ) const { GPOS_ASSERT(NULL != pxfctxt); GPOS_ASSERT(FPromising(pxfctxt->Pmp(), this, pexpr)); GPOS_ASSERT(FCheckPattern(pexpr)); IMemoryPool *mp = pxfctxt->Pmp(); // extract components CExpression *pexprOuter = (*pexpr)[0]; CExpression *pexprInner = (*pexpr)[1]; CExpression *pexprScalar = (*pexpr)[2]; pexprOuter->AddRef(); pexprInner->AddRef(); pexprScalar->AddRef(); // construct grouping columns by collecting used columns in the join predicate // that come from join's inner child CColRefSet *pcrsOuterOutput = CDrvdPropRelational::GetRelationalProperties(pexprOuter->PdpDerive())->PcrsOutput(); CColRefSet *pcrsUsed = CDrvdPropScalar::GetDrvdScalarProps(pexprScalar->PdpDerive())->PcrsUsed(); CColRefSet *pcrsGb = GPOS_NEW(mp) CColRefSet(mp); pcrsGb->Include(pcrsUsed); pcrsGb->Difference(pcrsOuterOutput); GPOS_ASSERT(0 < pcrsGb->Size()); CKeyCollection *pkc = CDrvdPropRelational::GetRelationalProperties(pexprInner->PdpDerive())->Pkc(); if (NULL == pkc || (NULL != pkc && !pkc->FKey(pcrsGb, false /*fExactMatch*/))) { // grouping columns do not cover a key on the inner side, // we need to create a group by on inner side CColRefArray *colref_array = pcrsGb->Pdrgpcr(mp); CExpression *pexprGb = GPOS_NEW(mp) CExpression ( mp, GPOS_NEW(mp) CLogicalGbAgg(mp, colref_array, COperator::EgbaggtypeGlobal /*egbaggtype*/), pexprInner, GPOS_NEW(mp) CExpression(mp, GPOS_NEW(mp) CScalarProjectList(mp)) ); pexprInner = pexprGb; } CExpression *pexprInnerJoin = CUtils::PexprLogicalJoin<CLogicalInnerJoin>(mp, pexprOuter, pexprInner, pexprScalar); pcrsGb->Release(); pxfres->Add(pexprInnerJoin); }
//--------------------------------------------------------------------------- // @function: // CXformSimplifyGbAgg::FDropGbAgg // // @doc: // Return true if GbAgg operator can be dropped because grouping // columns include a key // //--------------------------------------------------------------------------- BOOL CXformSimplifyGbAgg::FDropGbAgg ( IMemoryPool *pmp, CExpression *pexpr, CXformResult *pxfres ) { CLogicalGbAgg *popAgg = CLogicalGbAgg::PopConvert(pexpr->Pop()); CExpression *pexprRelational = (*pexpr)[0]; CExpression *pexprProjectList = (*pexpr)[1]; if (0 < pexprProjectList->UlArity()) { // GbAgg cannot be dropped if Agg functions are computed return false; } CKeyCollection *pkc = CDrvdPropRelational::Pdprel(pexprRelational->PdpDerive())->Pkc(); if (NULL == pkc) { // relational child does not have key return false; } const ULONG ulKeys = pkc->UlKeys(); BOOL fDrop = false; for (ULONG ul = 0; !fDrop && ul < ulKeys; ul++) { DrgPcr *pdrgpcrKey = pkc->PdrgpcrKey(pmp, ul); CColRefSet *pcrs = GPOS_NEW(pmp) CColRefSet(pmp, pdrgpcrKey); pdrgpcrKey->Release(); CColRefSet *pcrsGrpCols = GPOS_NEW(pmp) CColRefSet(pmp); pcrsGrpCols->Include(popAgg->Pdrgpcr()); BOOL fGrpColsHasKey = pcrsGrpCols->FSubset(pcrs); pcrs->Release(); pcrsGrpCols->Release(); if (fGrpColsHasKey) { // Gb operator can be dropped pexprRelational->AddRef(); CExpression *pexprResult = CUtils::PexprLogicalSelect(pmp, pexprRelational, CPredicateUtils::PexprConjunction(pmp, NULL)); pxfres->Add(pexprResult); fDrop = true; } } return fDrop; }
//--------------------------------------------------------------------------- // @function: // CPhysicalStreamAgg::PosRequiredStreamAgg // // @doc: // Compute required sort columns of the n-th child // //--------------------------------------------------------------------------- COrderSpec * CPhysicalStreamAgg::PosRequiredStreamAgg ( IMemoryPool *mp, CExpressionHandle &exprhdl, COrderSpec *posRequired, ULONG #ifdef GPOS_DEBUG child_index #endif // GPOS_DEBUG , CColRefArray *pdrgpcrGrp ) const { GPOS_ASSERT(0 == child_index); COrderSpec *pos = PosCovering(mp, posRequired, pdrgpcrGrp); if (NULL == pos) { // failed to find a covering order spec, use local order spec m_pos->AddRef(); pos = m_pos; } // extract sort columns from order spec CColRefSet *pcrs = pos->PcrsUsed(mp); // get key collection of the relational child CKeyCollection *pkc = exprhdl.GetRelationalProperties(0)->Pkc(); if (NULL != pkc && pkc->FKey(pcrs, false /*fExactMatch*/)) { CColRefSet *pcrsReqd = posRequired->PcrsUsed(m_mp); BOOL fUsesDefinedCols = FUnaryUsesDefinedColumns(pcrsReqd, exprhdl); pcrsReqd->Release(); if (!fUsesDefinedCols) { // we are grouping on child's key, // stream agg does not need to sort child and we can pass through input spec pos->Release(); posRequired->AddRef(); pos = posRequired; } } pcrs->Release(); return pos; }
//--------------------------------------------------------------------------- // @function: // CLogical::PkcDeriveKeysPassThru // // @doc: // Addref and return keys of n-th child // //--------------------------------------------------------------------------- CKeyCollection * CLogical::PkcDeriveKeysPassThru ( CExpressionHandle &exprhdl, ULONG ulChild ) { CKeyCollection *pkcLeft = exprhdl.Pdprel(ulChild)->Pkc(); // key collection may be NULL if (NULL != pkcLeft) { pkcLeft->AddRef(); } return pkcLeft; }