//--------------------------------------------------------------------------- // @function: // CXformDifferenceAll2LeftAntiSemiJoin::Transform // // @doc: // Actual transformation // //--------------------------------------------------------------------------- void CXformDifferenceAll2LeftAntiSemiJoin::Transform ( CXformContext *pxfctxt, CXformResult *pxfres, CExpression *pexpr ) const { GPOS_ASSERT(NULL != pxfctxt); GPOS_ASSERT(FPromising(pxfctxt->Pmp(), this, pexpr)); GPOS_ASSERT(FCheckPattern(pexpr)); IMemoryPool *pmp = pxfctxt->Pmp(); // TODO: , Jan 8th 2013, we currently only handle difference all // operators with two children GPOS_ASSERT(2 == pexpr->UlArity()); // extract components CExpression *pexprLeftChild = (*pexpr)[0]; CExpression *pexprRightChild = (*pexpr)[1]; CLogicalDifferenceAll *popDifferenceAll = CLogicalDifferenceAll::PopConvert(pexpr->Pop()); DrgDrgPcr *pdrgpdrgpcrInput = popDifferenceAll->PdrgpdrgpcrInput(); CExpression *pexprLeftWindow = CXformUtils::PexprWindowWithRowNumber(pmp, pexprLeftChild, (*pdrgpdrgpcrInput)[0]); CExpression *pexprRightWindow = CXformUtils::PexprWindowWithRowNumber(pmp, pexprRightChild, (*pdrgpdrgpcrInput)[1]); DrgDrgPcr *pdrgpdrgpcrInputNew = GPOS_NEW(pmp) DrgDrgPcr(pmp); DrgPcr *pdrgpcrLeftNew = CUtils::PdrgpcrExactCopy(pmp, (*pdrgpdrgpcrInput)[0]); pdrgpcrLeftNew->Append(CXformUtils::PcrProjectElement(pexprLeftWindow, 0 /* row_number window function*/)); DrgPcr *pdrgpcrRightNew = CUtils::PdrgpcrExactCopy(pmp, (*pdrgpdrgpcrInput)[1]); pdrgpcrRightNew->Append(CXformUtils::PcrProjectElement(pexprRightWindow, 0 /* row_number window function*/)); pdrgpdrgpcrInputNew->Append(pdrgpcrLeftNew); pdrgpdrgpcrInputNew->Append(pdrgpcrRightNew); // generate the scalar condition for the left anti-semi join CExpression *pexprScCond = CUtils::PexprConjINDFCond(pmp, pdrgpdrgpcrInputNew); // assemble the new left anti-semi join logical operator CExpression *pexprLASJ = GPOS_NEW(pmp) CExpression ( pmp, GPOS_NEW(pmp) CLogicalLeftAntiSemiJoin(pmp), pexprLeftWindow, pexprRightWindow, pexprScCond ); // clean up pdrgpdrgpcrInputNew->Release(); // add alternative to results pxfres->Add(pexprLASJ); }
//--------------------------------------------------------------------------- // @function: // CLogical::PdrgpdrgpcrCreatePartCols // // @doc: // Initialize array of partition columns from the array with their indexes // //--------------------------------------------------------------------------- DrgDrgPcr * CLogical::PdrgpdrgpcrCreatePartCols ( IMemoryPool *pmp, DrgPcr *pdrgpcr, const DrgPul *pdrgpulPart ) { GPOS_ASSERT(NULL != pdrgpcr && "Output columns cannot be NULL"); GPOS_ASSERT(NULL != pdrgpulPart); DrgDrgPcr *pdrgpdrgpcrPart = GPOS_NEW(pmp) DrgDrgPcr(pmp); const ULONG ulPartCols = pdrgpulPart->UlLength(); GPOS_ASSERT(0 < ulPartCols); for (ULONG ul = 0; ul < ulPartCols; ul++) { ULONG ulCol = *((*pdrgpulPart)[ul]); CColRef *pcr = (*pdrgpcr)[ulCol]; DrgPcr * pdrgpcrCurr = GPOS_NEW(pmp) DrgPcr(pmp); pdrgpcrCurr->Append(pcr); pdrgpdrgpcrPart->Append(pdrgpcrCurr); } return pdrgpdrgpcrPart; }
//--------------------------------------------------------------------------- // @function: // CPartKeys::PpartkeysRemap // // @doc: // Create a new PartKeys object from the current one by remapping the // keys using the given hashmap // //--------------------------------------------------------------------------- CPartKeys * CPartKeys::PpartkeysRemap ( IMemoryPool *pmp, HMUlCr *phmulcr ) const { GPOS_ASSERT(NULL != phmulcr); DrgDrgPcr *pdrgpdrgpcr = GPOS_NEW(pmp) DrgDrgPcr(pmp); for (ULONG ul = 0; ul < m_ulLevels; ul++) { CColRef *pcr = CUtils::PcrRemap(PcrKey(ul), phmulcr, false /*fMustExist*/); DrgPcr *pdrgpcr = GPOS_NEW(pmp) DrgPcr(pmp); pdrgpcr->Append(pcr); pdrgpdrgpcr->Append(pdrgpcr); } return GPOS_NEW(pmp) CPartKeys(pdrgpdrgpcr); }
//--------------------------------------------------------------------------- // @function: // CPartKeys::PpartkeysCopy // // @doc: // Copy part key into the given memory pool // //--------------------------------------------------------------------------- CPartKeys * CPartKeys::PpartkeysCopy ( IMemoryPool *pmp ) { DrgDrgPcr *pdrgpdrgpcrCopy = GPOS_NEW(pmp) DrgDrgPcr(pmp); const ULONG ulLength = m_pdrgpdrgpcr->UlLength(); for (ULONG ul = 0; ul < ulLength; ul++) { DrgPcr *pdrgpcr = (*m_pdrgpdrgpcr)[ul]; DrgPcr *pdrgpcrCopy = GPOS_NEW(pmp) DrgPcr(pmp); const ULONG ulCols = pdrgpcr->UlLength(); for (ULONG ulCol = 0; ulCol < ulCols; ulCol++) { pdrgpcrCopy->Append((*pdrgpcr)[ulCol]); } pdrgpdrgpcrCopy->Append(pdrgpcrCopy); } return GPOS_NEW(pmp) CPartKeys(pdrgpdrgpcrCopy); }
//--------------------------------------------------------------------------- // @function: // CXformSelect2PartialDynamicIndexGet::CreatePartialIndexGetPlan // // @doc: // Create a plan as a union of the given partial index get candidates and // possibly a dynamic table scan // //--------------------------------------------------------------------------- void CXformSelect2PartialDynamicIndexGet::CreatePartialIndexGetPlan ( IMemoryPool *pmp, CExpression *pexpr, DrgPpartdig *pdrgppartdig, const IMDRelation *pmdrel, CXformResult *pxfres ) const { CExpression *pexprRelational = (*pexpr)[0]; CExpression *pexprScalar = (*pexpr)[1]; CLogicalDynamicGet *popGet = CLogicalDynamicGet::PopConvert(pexprRelational->Pop()); DrgPcr *pdrgpcrGet = popGet->PdrgpcrOutput(); const ULONG ulPartialIndexes = pdrgppartdig->UlLength(); DrgDrgPcr *pdrgpdrgpcrInput = GPOS_NEW(pmp) DrgDrgPcr(pmp); DrgPexpr *pdrgpexprInput = GPOS_NEW(pmp) DrgPexpr(pmp); for (ULONG ul = 0; ul < ulPartialIndexes; ul++) { SPartDynamicIndexGetInfo *ppartdig = (*pdrgppartdig)[ul]; const IMDIndex *pmdindex = ppartdig->m_pmdindex; CPartConstraint *ppartcnstr = ppartdig->m_ppartcnstr; DrgPexpr *pdrgpexprIndex = ppartdig->m_pdrgpexprIndex; DrgPexpr *pdrgpexprResidual = ppartdig->m_pdrgpexprResidual; DrgPcr *pdrgpcrNew = pdrgpcrGet; if (0 < ul) { pdrgpcrNew = CUtils::PdrgpcrCopy(pmp, pdrgpcrGet); } else { pdrgpcrNew->AddRef(); } CExpression *pexprDynamicScan = NULL; if (NULL != pmdindex) { pexprDynamicScan = CXformUtils::PexprPartialDynamicIndexGet ( pmp, popGet, pexpr->Pop()->UlOpId(), pdrgpexprIndex, pdrgpexprResidual, pdrgpcrNew, pmdindex, pmdrel, ppartcnstr, NULL, // pcrsAcceptedOuterRefs NULL, // pdrgpcrOuter NULL // pdrgpcrNewOuter ); } else { pexprDynamicScan = PexprSelectOverDynamicGet ( pmp, popGet, pexprScalar, pdrgpcrNew, ppartcnstr ); } GPOS_ASSERT(NULL != pexprDynamicScan); pdrgpdrgpcrInput->Append(pdrgpcrNew); pdrgpexprInput->Append(pexprDynamicScan); } ULONG ulInput = pdrgpexprInput->UlLength(); if (0 < ulInput) { CExpression *pexprResult = NULL; if (1 < ulInput) { pdrgpcrGet->AddRef(); DrgPcr *pdrgpcrOuter = pdrgpcrGet; // construct a new union all operator pexprResult = GPOS_NEW(pmp) CExpression ( pmp, GPOS_NEW(pmp) CLogicalUnionAll(pmp, pdrgpcrOuter, pdrgpdrgpcrInput, popGet->UlScanId()), pdrgpexprInput ); } else { pexprResult = (*pdrgpexprInput)[0]; pexprResult->AddRef(); // clean up pdrgpexprInput->Release(); pdrgpdrgpcrInput->Release(); } // if scalar expression involves the partitioning key, keep a SELECT node // on top for the purposes of partition selection DrgDrgPcr *pdrgpdrgpcrPartKeys = popGet->PdrgpdrgpcrPart(); CExpression *pexprPredOnPartKey = CPredicateUtils::PexprExtractPredicatesOnPartKeys ( pmp, pexprScalar, pdrgpdrgpcrPartKeys, NULL, /*pcrsAllowedRefs*/ true /*fUseConstraints*/ ); if (NULL != pexprPredOnPartKey) { pexprResult = GPOS_NEW(pmp) CExpression(pmp, GPOS_NEW(pmp) CLogicalSelect(pmp), pexprResult, pexprPredOnPartKey); } pxfres->Add(pexprResult); return; } // clean up pdrgpdrgpcrInput->Release(); pdrgpexprInput->Release(); }