//--------------------------------------------------------------------------- // @function: // CStatsPredUtils::Pdrgpstatsjoin // // @doc: // Extract statistics join information // //--------------------------------------------------------------------------- DrgPstatsjoin * CStatsPredUtils::Pdrgpstatsjoin ( IMemoryPool *pmp, CExpressionHandle &exprhdl ) { // in case of subquery in join predicate, we return empty stats if (exprhdl.Pdpscalar(exprhdl.UlArity() - 1)->FHasSubquery()) { return GPOS_NEW(pmp) DrgPstatsjoin(pmp); } DrgPcrs *pdrgpcrsOutput = GPOS_NEW(pmp) DrgPcrs(pmp); const ULONG ulSize = exprhdl.UlArity(); for (ULONG ul = 0; ul < ulSize - 1; ul++) { CColRefSet *pcrs = exprhdl.Pdprel(ul)->PcrsOutput(); pcrs->AddRef(); pdrgpcrsOutput->Append(pcrs); } // TODO: 02/29/2012 replace with constraint property info once available CExpression *pexprScalar = exprhdl.PexprScalarChild(exprhdl.UlArity() - 1); CColRefSet *pcrsOuterRefs = exprhdl.Pdprel()->PcrsOuter(); DrgPstatsjoin *pdrgpstats = Pdrgpstatsjoin(pmp, exprhdl, pexprScalar, pdrgpcrsOutput, pcrsOuterRefs); // clean up pdrgpcrsOutput->Release(); return pdrgpstats; }
//--------------------------------------------------------------------------- // @function: // CLogical::PcrsDeriveNotNullPassThruOuter // // @doc: // Common case of deriving not null columns by passing through // not null columns from the outer child // //--------------------------------------------------------------------------- CColRefSet * CLogical::PcrsDeriveNotNullPassThruOuter ( CExpressionHandle &exprhdl ) { // may have additional children that are ignored, e.g., scalar children GPOS_ASSERT(1 <= exprhdl.UlArity()); CColRefSet *pcrs = exprhdl.Pdprel(0)->PcrsNotNull(); pcrs->AddRef(); return pcrs; }
//--------------------------------------------------------------------------- // @function: // CLogicalSequence::PcrsDeriveOutput // // @doc: // Derive output columns // //--------------------------------------------------------------------------- CColRefSet * CLogicalSequence::PcrsDeriveOutput ( IMemoryPool *, // mp CExpressionHandle &exprhdl ) { GPOS_ASSERT(1 <= exprhdl.Arity()); // get output columns of last child CColRefSet *pcrs = exprhdl.GetRelationalProperties(exprhdl.Arity() - 1)->PcrsOutput(); pcrs->AddRef(); return pcrs; }
//--------------------------------------------------------------------------- // @function: // CLogicalSetOp::PcrsStat // // @doc: // Compute required stats columns // //--------------------------------------------------------------------------- CColRefSet * CLogicalSetOp::PcrsStat ( IMemoryPool *, // pmp CExpressionHandle &, //exprhdl, CColRefSet *, //pcrsInput ULONG ulChildIndex ) const { CColRefSet *pcrs = (*m_pdrgpcrsInput)[ulChildIndex]; pcrs->AddRef(); return pcrs; }
//--------------------------------------------------------------------------- // @function: // CPhysicalUnionAll::PcrsRequired // // @doc: // Compute required columns of the n-th child; // we only compute required columns for the relational child; // //--------------------------------------------------------------------------- CColRefSet * CPhysicalUnionAll::PcrsRequired ( IMemoryPool *, // mp CExpressionHandle &,//exprhdl, CColRefSet *, //pcrsRequired, ULONG child_index, CDrvdProp2dArray *, // pdrgpdpCtxt ULONG // ulOptReq ) { CColRefSet *pcrs = PcrsInput(child_index); pcrs->AddRef(); return pcrs; }
//--------------------------------------------------------------------------- // @function: // CPhysicalUnionAll::PcrsRequired // // @doc: // Compute required columns of the n-th child; // we only compute required columns for the relational child; // //--------------------------------------------------------------------------- CColRefSet * CPhysicalUnionAll::PcrsRequired ( IMemoryPool *, // pmp CExpressionHandle &,//exprhdl, CColRefSet *, //pcrsRequired, ULONG ulChildIndex, DrgPdp *, // pdrgpdpCtxt ULONG // ulOptReq ) { GPOS_ASSERT(NULL != m_pdrgpcrsInput); CColRefSet *pcrs = (*m_pdrgpcrsInput)[ulChildIndex]; pcrs->AddRef(); return pcrs; }
//--------------------------------------------------------------------------- // @function: // CPhysical::PcrsChildReqd // // @doc: // Helper for computing required output columns of the n-th child; // the caller must be an operator whose ulScalarIndex-th child is a // scalar // //--------------------------------------------------------------------------- CColRefSet * CPhysical::PcrsChildReqd ( IMemoryPool *mp, CExpressionHandle &exprhdl, CColRefSet *pcrsRequired, ULONG child_index, ULONG ulScalarIndex ) { pcrsRequired->AddRef(); CReqdColsRequest *prcr = GPOS_NEW(mp) CReqdColsRequest(pcrsRequired, child_index, ulScalarIndex); CColRefSet *pcrs = NULL; { // scope of AutoMutex CAutoMutex am(m_mutex); am.Lock(); // lookup required columns map first pcrs = m_phmrcr->Find(prcr); if (NULL != pcrs) { prcr->Release(); pcrs->AddRef(); return pcrs; } } // request was not found in map -- we need to compute it pcrs = GPOS_NEW(mp) CColRefSet(mp, *pcrsRequired); if (gpos::ulong_max != ulScalarIndex) { // include used columns and exclude defined columns of scalar child pcrs->Union(exprhdl.GetDrvdScalarProps(ulScalarIndex)->PcrsUsed()); pcrs->Exclude(exprhdl.GetDrvdScalarProps(ulScalarIndex)->PcrsDefined()); } // intersect computed column set with child's output columns pcrs->Intersection(exprhdl.GetRelationalProperties(child_index)->PcrsOutput()); // lookup map again to handle concurrent map lookup/insertion { // scope of AutoMutex CAutoMutex am(m_mutex); am.Lock(); CColRefSet *pcrsFound = m_phmrcr->Find(prcr); if (NULL != pcrsFound) { // request was found now -- release computed request and use the found request prcr->Release(); pcrs->Release(); pcrsFound->AddRef(); pcrs = pcrsFound; } else { // new request -- insert request in map pcrs->AddRef(); #ifdef GPOS_DEBUG BOOL fSuccess = #endif // GPOS_DEBUG m_phmrcr->Insert(prcr, pcrs); GPOS_ASSERT(fSuccess); } } return pcrs; }
//--------------------------------------------------------------------------- // @function: // CXformSubqJoin2Apply::PexprSubqueryPushdown // // @doc: // Push down subquery below join // //--------------------------------------------------------------------------- CExpression * CXformSubqJoin2Apply::PexprSubqueryPushDown ( IMemoryPool *mp, CExpression *pexpr, BOOL fEnforceCorrelatedApply ) { GPOS_ASSERT(NULL != pexpr); GPOS_ASSERT(COperator::EopLogicalSelect == pexpr->Pop()->Eopid()); CExpression *pexprJoin = (*pexpr)[0]; const ULONG arity = pexprJoin->Arity(); CExpression *pexprScalar = (*pexpr)[1]; CExpression *join_pred_expr = (*pexprJoin)[arity - 1]; // collect output columns of all logical children CColRefSetArray *pdrgpcrs = GPOS_NEW(mp) CColRefSetArray(mp); CExpressionArrays *pdrgpdrgpexprSubqs = GPOS_NEW(mp) CExpressionArrays(mp); for (ULONG ul = 0; ul < arity - 1; ul++) { CExpression *pexprChild = (*pexprJoin)[ul]; CColRefSet *pcrsOutput = CDrvdPropRelational::GetRelationalProperties(pexprChild->PdpDerive())->PcrsOutput(); pcrsOutput->AddRef(); pdrgpcrs->Append(pcrsOutput); pdrgpdrgpexprSubqs->Append(GPOS_NEW(mp) CExpressionArray(mp)); } // collect subqueries that exclusively use columns from each join child CollectSubqueries(mp, pexprScalar, pdrgpcrs, pdrgpdrgpexprSubqs); // create new join children by pushing subqueries to Project nodes on top // of corresponding join children CExpressionArray *pdrgpexprNewChildren = GPOS_NEW(mp) CExpressionArray(mp); ExprToColRefMap *phmexprcr = GPOS_NEW(mp) ExprToColRefMap(mp); for (ULONG ulChild = 0; ulChild < arity - 1; ulChild++) { CExpression *pexprChild = (*pexprJoin)[ulChild]; pexprChild->AddRef(); CExpression *pexprNewChild = pexprChild; CExpressionArray *pdrgpexprSubqs = (*pdrgpdrgpexprSubqs)[ulChild]; const ULONG ulSubqs = pdrgpexprSubqs->Size(); if (0 < ulSubqs) { // join child has pushable subqueries pexprNewChild = CUtils::PexprAddProjection(mp, pexprChild, pdrgpexprSubqs); CExpression *pexprPrjList = (*pexprNewChild)[1]; // add pushed subqueries to map for (ULONG ulSubq = 0; ulSubq < ulSubqs; ulSubq++) { CExpression *pexprSubq = (*pdrgpexprSubqs)[ulSubq]; pexprSubq->AddRef(); CColRef *colref = CScalarProjectElement::PopConvert((*pexprPrjList)[ulSubq]->Pop())->Pcr(); #ifdef GPOS_DEBUG BOOL fInserted = #endif // GPOS_DEBUG phmexprcr->Insert(pexprSubq, colref); GPOS_ASSERT(fInserted); } // unnest subqueries in newly created child CExpression *pexprUnnested = PexprSubqueryUnnest(mp, pexprNewChild, fEnforceCorrelatedApply); if (NULL != pexprUnnested) { pexprNewChild->Release(); pexprNewChild = pexprUnnested; } } pdrgpexprNewChildren->Append(pexprNewChild); } join_pred_expr->AddRef(); pdrgpexprNewChildren->Append(join_pred_expr); // replace subqueries in the original scalar expression with // scalar identifiers based on constructed map CExpression *pexprNewScalar = PexprReplaceSubqueries(mp, pexprScalar, phmexprcr); phmexprcr->Release(); pdrgpcrs->Release(); pdrgpdrgpexprSubqs->Release(); // build the new join expression COperator *pop = pexprJoin->Pop(); pop->AddRef(); CExpression *pexprNewJoin = GPOS_NEW(mp) CExpression(mp, pop, pdrgpexprNewChildren); // return a new Select expression pop = pexpr->Pop(); pop->AddRef(); return GPOS_NEW(mp) CExpression(mp, pop, pexprNewJoin, pexprNewScalar); }