//--------------------------------------------------------------------------- // @function: // CParseHandlerScalarSubPlanParamList::EndElement // // @doc: // Processes a Xerces end element event // //--------------------------------------------------------------------------- void CParseHandlerScalarSubPlanParamList::EndElement ( const XMLCh* const, // xmlszUri, const XMLCh* const xmlszLocalname, const XMLCh* const // xmlszQname ) { if(0 != XMLString::compareString(CDXLTokens::XmlstrToken(EdxltokenScalarSubPlanParamList), xmlszLocalname) && NULL != m_pdxln) { CWStringDynamic *pstr = CDXLUtils::PstrFromXMLCh(m_pphm->Pmm(), xmlszLocalname); GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiDXLUnexpectedTag, pstr->Wsz()); } const ULONG ulSize = this->UlLength(); // add constructed children from child parse handlers for (ULONG ul = 0; ul < ulSize; ul++) { CParseHandlerScalarSubPlanParam *pphParam = dynamic_cast<CParseHandlerScalarSubPlanParam *>((*this)[ul]); CDXLColRef *pdxlcr = pphParam->Pdxlcr(); IMDId *pmdid = pphParam->Pmdid(); pdxlcr->AddRef(); pmdid->AddRef(); m_pdrgdxlcr->Append(pdxlcr); m_pdrgmdid->Append(pmdid); } // deactivate handler m_pphm->DeactivateHandler(); }
//--------------------------------------------------------------------------- // @function: // CLogical::PosFromIndex // // @doc: // Compute an order spec based on an index // //--------------------------------------------------------------------------- COrderSpec * CLogical::PosFromIndex ( IMemoryPool *pmp, const IMDIndex *pmdindex, DrgPcr *pdrgpcr ) { // compute the order spec COrderSpec *pos = GPOS_NEW(pmp) COrderSpec(pmp); const ULONG ulLenIncludeCols = pmdindex->UlKeys(); for (ULONG ul = 0; ul < ulLenIncludeCols; ul++) { ULONG ulPos = pmdindex->UlKey(ul); CColRef *pcr = (*pdrgpcr)[ulPos]; IMDId *pmdid = pcr->Pmdtype()->PmdidCmp(IMDType::EcmptL); pmdid->AddRef(); // TODO: March 27th 2012; we hard-code NULL treatment // need to revisit pos->Append(pmdid, pcr, COrderSpec::EntLast); } return pos; }
//--------------------------------------------------------------------------- // @function: // CScalarAggFunc::CScalarAggFunc // // @doc: // Ctor // //--------------------------------------------------------------------------- CScalarAggFunc::CScalarAggFunc ( IMemoryPool *pmp, IMDId *pmdidAggFunc, IMDId *pmdidResolvedRetType, const CWStringConst *pstrAggFunc, BOOL fDistinct, EAggfuncStage eaggfuncstage, BOOL fSplit ) : CScalar(pmp), m_pmdidAggFunc(pmdidAggFunc), m_pmdidResolvedRetType(pmdidResolvedRetType), m_pmdidRetType(NULL), m_pstrAggFunc(pstrAggFunc), m_fDistinct(fDistinct), m_eaggfuncstage(eaggfuncstage), m_fSplit(fSplit) { GPOS_ASSERT(NULL != pmdidAggFunc); GPOS_ASSERT(NULL != pstrAggFunc); GPOS_ASSERT(pmdidAggFunc->FValid()); GPOS_ASSERT_IMP(NULL != pmdidResolvedRetType, pmdidResolvedRetType->FValid()); GPOS_ASSERT(EaggfuncstageSentinel > eaggfuncstage); // store id of type obtained by looking up MD cache IMDId *pmdid = PmdidLookupReturnType(m_pmdidAggFunc, (EaggfuncstageGlobal == m_eaggfuncstage)); pmdid->AddRef(); m_pmdidRetType = pmdid; }
//--------------------------------------------------------------------------- // @function: // CPhysicalStreamAgg::PosCovering // // @doc: // Construct order spec on grouping column so that it covers required // order spec, the function returns NULL if no covering order spec // can be created // //--------------------------------------------------------------------------- COrderSpec * CPhysicalStreamAgg::PosCovering ( IMemoryPool *mp, COrderSpec *posRequired, CColRefArray *pdrgpcrGrp ) const { GPOS_ASSERT(NULL != posRequired); if (0 == posRequired->UlSortColumns()) { // required order must be non-empty return NULL; } // create a set of required sort columns CColRefSet *pcrsReqd = posRequired->PcrsUsed(mp); COrderSpec *pos = NULL; CColRefSet *pcrsGrpCols = GPOS_NEW(mp) CColRefSet(mp, pdrgpcrGrp); if (pcrsGrpCols->ContainsAll(pcrsReqd)) { // required order columns are included in grouping columns, we can // construct a covering order spec pos = GPOS_NEW(mp) COrderSpec(mp); // extract order expressions from required order const ULONG ulReqdSortCols = posRequired->UlSortColumns(); for (ULONG ul = 0; ul < ulReqdSortCols; ul++) { CColRef *colref = const_cast<CColRef *>(posRequired->Pcr(ul)); IMDId *mdid = posRequired->GetMdIdSortOp(ul); COrderSpec::ENullTreatment ent = posRequired->Ent(ul); mdid->AddRef(); pos->Append(mdid, colref, ent); } // augment order with remaining grouping columns const ULONG size = pdrgpcrGrp->Size(); for (ULONG ul = 0; ul < size; ul++) { CColRef *colref = (*pdrgpcrGrp)[ul]; if (!pcrsReqd->FMember(colref)) { IMDId *mdid = colref->RetrieveType()->GetMdidForCmpType(IMDType::EcmptL); mdid->AddRef(); pos->Append(mdid, colref, COrderSpec::EntLast); } } } pcrsGrpCols->Release(); pcrsReqd->Release(); return pos; }
//--------------------------------------------------------------------------- // @function: // CPartIndexMap::AddUnresolved // // @doc: // Helper to add part-index id's found in the first map and are // unresolved based on the second map // // For example, if the first and second map contain the following entries: // pimFst: // (partindexid: 1, consumer, part cnstr: 5->[1,3)), // (partindexid: 2, consumer, part cnstr: <>), // pimSnd: // (partindexid: 1, consumer, part cnstr: 6->(4,5))), // (partindexid: 2, producer, part cnstr: <>), // (partindexid: 3, producer, part cnstr: <>) // the result will be: // (partindexid: 1, consumer, part cnstr: 5->[1,3), 6->(4,5)), // part constraint get combined // (partindexid: 2, resolver, part cnstr: <>), // consumer+producer=resolver // (partindexid: 3, producer, part cnstr: <>) // no match for part index id 3: copy out // //--------------------------------------------------------------------------- void CPartIndexMap::AddUnresolved ( IMemoryPool *pmp, const CPartIndexMap &pimFst, const CPartIndexMap &pimSnd, CPartIndexMap* ppimResult ) { // iterate on first map and lookup entries in second map PartIndexMapIter pimiFst(pimFst.m_pim); while (pimiFst.FAdvance()) { const CPartTableInfo *pptiFst = pimiFst.Pt(); ULONG ulScanId = pptiFst->UlScanId(); EPartIndexManipulator epimFst = pptiFst->Epim(); ULONG ulPropagatorsFst = pptiFst->UlExpectedPropagators(); if (NULL != ppimResult->PptiLookup(ulScanId)) { // skip entries already in the result map continue; } // check if entry exists in second map CPartTableInfo *pptiSnd = pimSnd.PptiLookup(ulScanId); EPartIndexManipulator epimResult = epimFst; ULONG ulPropagatorsResult = ulPropagatorsFst; PartCnstrMap *ppartcnstrmapSnd = NULL; if (NULL != pptiSnd) { EPartIndexManipulator epimSnd = pptiSnd->Epim(); ULONG ulPropagatorsSnd = pptiSnd->UlExpectedPropagators(); GPOS_ASSERT_IMP(epimFst == EpimConsumer && epimSnd == EpimConsumer, ulPropagatorsFst == ulPropagatorsSnd); ResolvePropagator(epimFst, ulPropagatorsFst, epimSnd, ulPropagatorsSnd, &epimResult, &ulPropagatorsResult); ppartcnstrmapSnd = pptiSnd->Ppartcnstrmap(); } // copy mdid and partition columns from part index map entry IMDId *pmdid = pptiFst->Pmdid(); DrgPpartkeys *pdrgppartkeys = pptiFst->Pdrgppartkeys(); CPartConstraint *ppartcnstrRel = pptiFst->PpartcnstrRel(); PartCnstrMap *ppartcnstrmap = CPartConstraint::PpartcnstrmapCombine(pmp, pptiFst->Ppartcnstrmap(), ppartcnstrmapSnd); pmdid->AddRef(); pdrgppartkeys->AddRef(); ppartcnstrRel->AddRef(); ppimResult->Insert(ulScanId, ppartcnstrmap, epimResult, ulPropagatorsResult, pmdid, pdrgppartkeys, ppartcnstrRel); } }
//--------------------------------------------------------------------------- // @function: // CPhysicalDML::PosComputeRequired // // @doc: // Compute required sort order based on the key information in the table // descriptor: // 1. If a table has no keys, no sort order is necessary. // // 2. If a table has keys, but they are not modified in the update, no sort // order is necessary. This relies on the fact that Split always produces // Delete tuples before Insert tuples, so we cannot have two versions of the // same tuple on the same time. Consider for example tuple (A: 1, B: 2), where // A is key and an update "set B=B+1". Since there cannot be any other tuple // with A=1, and the tuple (1,2) is deleted before tuple (1,3) gets inserted, // we don't need to enforce specific order of deletes and inserts. // // 3. If the update changes a key column, enforce order on the Action column // to deliver Delete tuples before Insert tuples. This is done to avoid a // conflict between a newly inserted tuple and an old tuple that is about to be // deleted. Consider table with tuples (A: 1),(A: 2), where A is key, and // update "set A=A+1". Split will generate tuples (1,"D"), (2,"I"), (2,"D"), (3,"I"). // If (2,"I") happens before (2,"D") we will have a violation of the key constraint. // Therefore we need to enforce sort order on Action to get all old tuples // tuples deleted before the new ones are inserted. // //--------------------------------------------------------------------------- COrderSpec * CPhysicalDML::PosComputeRequired ( IMemoryPool *pmp, CTableDescriptor *ptabdesc ) { COrderSpec *pos = GPOS_NEW(pmp) COrderSpec(pmp); const DrgPbs *pdrgpbsKeys = ptabdesc->PdrgpbsKeys(); if (1 < pdrgpbsKeys->UlLength() && CLogicalDML::EdmlUpdate == m_edmlop) { // if this is an update on the target table's keys, enforce order on // the action column, see explanation in function's comment const ULONG ulKeySets = pdrgpbsKeys->UlLength(); BOOL fNeedsSort = false; for (ULONG ul = 0; ul < ulKeySets && !fNeedsSort; ul++) { CBitSet *pbs = (*pdrgpbsKeys)[ul]; if (!pbs->FDisjoint(m_pbsModified)) { fNeedsSort = true; break; } } if (fNeedsSort) { IMDId *pmdid = m_pcrAction->Pmdtype()->PmdidCmp(IMDType::EcmptL); pmdid->AddRef(); pos->Append(pmdid, m_pcrAction, COrderSpec::EntAuto); } } else if (m_ptabdesc->FPartitioned()) { COptimizerConfig *poconf = COptCtxt::PoctxtFromTLS()->Poconf(); BOOL fInsertSortOnParquet = FInsertSortOnParquet(); BOOL fInsertSortOnRows = FInsertSortOnRows(poconf); if (fInsertSortOnParquet || fInsertSortOnRows) { GPOS_ASSERT(CLogicalDML::EdmlInsert == m_edmlop); m_fInputSorted = true; // if this is an INSERT over a partitioned Parquet or Row-oriented table, // sort tuples by their table oid IMDId *pmdid = m_pcrTableOid->Pmdtype()->PmdidCmp(IMDType::EcmptL); pmdid->AddRef(); pos->Append(pmdid, m_pcrTableOid, COrderSpec::EntAuto); } } return pos; }
//--------------------------------------------------------------------------- // @function: // CPartIndexMap::PpimPartitionSelector // // @doc: // Return a new part index map for a partition selector with the given // scan id, and the given number of expected selectors above it // //--------------------------------------------------------------------------- CPartIndexMap * CPartIndexMap::PpimPartitionSelector ( IMemoryPool *pmp, ULONG ulScanId, ULONG ulExpectedFromReq ) const { CPartIndexMap *ppimResult = GPOS_NEW(pmp) CPartIndexMap(pmp); PartIndexMapIter pimi(m_pim); while (pimi.FAdvance()) { const CPartTableInfo *ppti = pimi.Pt(); PartCnstrMap *ppartcnstrmap = ppti->Ppartcnstrmap(); IMDId *pmdid = ppti->Pmdid(); DrgPpartkeys *pdrgppartkeys = ppti->Pdrgppartkeys(); CPartConstraint *ppartcnstrRel = ppti->PpartcnstrRel(); ppartcnstrmap->AddRef(); pmdid->AddRef(); pdrgppartkeys->AddRef(); ppartcnstrRel->AddRef(); EPartIndexManipulator epim = ppti->Epim(); ULONG ulExpectedPropagators = ppti->UlExpectedPropagators(); if (ppti->UlScanId() == ulScanId) { if (0 == ulExpectedFromReq) { // this are no other expected partition selectors // so this scan id is resolved epim = EpimResolver; ulExpectedPropagators = 0; } else { // this is not resolved yet epim = EpimConsumer; ulExpectedPropagators = ulExpectedFromReq; } } ppimResult->Insert(ppti->UlScanId(), ppartcnstrmap, epim, ulExpectedPropagators, pmdid, pdrgppartkeys, ppartcnstrRel); } return ppimResult; }
//--------------------------------------------------------------------------- // @function: // CLogicalDynamicGetBase::PpartinfoDerive // // @doc: // Derive partition consumer info // //--------------------------------------------------------------------------- CPartInfo * CLogicalDynamicGetBase::PpartinfoDerive ( IMemoryPool *pmp, CExpressionHandle & // exprhdl ) const { IMDId *pmdid = m_ptabdesc->Pmdid(); pmdid->AddRef(); m_pdrgpdrgpcrPart->AddRef(); m_ppartcnstrRel->AddRef(); CPartInfo *ppartinfo = GPOS_NEW(pmp) CPartInfo(pmp); ppartinfo->AddPartConsumer(pmp, m_ulScanId, pmdid, m_pdrgpdrgpcrPart, m_ppartcnstrRel); return ppartinfo; }
//--------------------------------------------------------------------------- // @function: // CMDProviderMemory::LoadMetadataObjectsFromArray // // @doc: // Loads the metadata objects from the given file // //--------------------------------------------------------------------------- void CMDProviderMemory::LoadMetadataObjectsFromArray ( IMemoryPool *pmp, DrgPimdobj *pdrgpmdobj ) { GPOS_ASSERT(NULL != pdrgpmdobj); // load metadata objects from the file CAutoRef<MDMap> a_pmdmap; m_pmdmap = GPOS_NEW(pmp) MDMap(pmp); a_pmdmap = m_pmdmap; const ULONG ulSize = pdrgpmdobj->UlLength(); // load objects into the hash map for (ULONG ul = 0; ul < ulSize; ul++) { GPOS_CHECK_ABORT; IMDCacheObject *pmdobj = (*pdrgpmdobj)[ul]; IMDId *pmdidKey = pmdobj->Pmdid(); pmdidKey->AddRef(); CAutoRef<IMDId> a_pmdidKey; a_pmdidKey = pmdidKey; CAutoP<CWStringDynamic> a_pstr; a_pstr = CDXLUtils::PstrSerializeMDObj(pmp, pmdobj, true /*fSerializeHeaders*/, false /*findent*/); GPOS_CHECK_ABORT; BOOL fInserted = m_pmdmap->FInsert(pmdidKey, a_pstr.Pt()); if (!fInserted) { GPOS_RAISE(gpdxl::ExmaMD, gpdxl::ExmiMDCacheEntryDuplicate, pmdidKey->Wsz()); } (void) a_pmdidKey.PtReset(); (void) a_pstr.PtReset(); } // safely completed loading (void) a_pmdmap.PtReset(); }
//--------------------------------------------------------------------------- // @function: // CPartInfo::CPartInfoEntry::PpartinfoentryCopy // // @doc: // Copy part info entry into given memory pool // //--------------------------------------------------------------------------- CPartInfo::CPartInfoEntry * CPartInfo::CPartInfoEntry::PpartinfoentryCopy ( IMemoryPool *pmp ) { IMDId *pmdid = Pmdid(); pmdid->AddRef(); // copy part keys DrgPpartkeys *pdrgppartkeysCopy = CPartKeys::PdrgppartkeysCopy(pmp, Pdrgppartkeys()); // copy part constraint using empty remapping to get exact copy HMUlCr *phmulcr = GPOS_NEW(pmp) HMUlCr(pmp); CPartConstraint *ppartcnstrRel = PpartcnstrRel()->PpartcnstrCopyWithRemappedColumns(pmp, phmulcr, false /*fMustExist*/); phmulcr->Release(); return GPOS_NEW(pmp) CPartInfoEntry(UlScanId(), pmdid, pdrgppartkeysCopy, ppartcnstrRel); }
//--------------------------------------------------------------------------- // @function: // CPhysicalDynamicScan::PpimDerive // // @doc: // Derive partition index map // //--------------------------------------------------------------------------- CPartIndexMap * CPhysicalDynamicScan::PpimDerive ( IMemoryPool *pmp, CExpressionHandle &, //exprhdl CDrvdPropCtxt *pdpctxt ) const { GPOS_ASSERT(NULL != pdpctxt); IMDId *pmdid = m_ptabdesc->Pmdid(); pmdid->AddRef(); m_pdrgpdrgpcrPart->AddRef(); m_ppartcnstr->AddRef(); m_ppartcnstrRel->AddRef(); ULONG ulExpectedPartitionSelectors = CDrvdPropCtxtPlan::PdpctxtplanConvert(pdpctxt)->UlExpectedPartitionSelectors(); return PpimDeriveFromDynamicScan(pmp, m_ulScanId, pmdid, m_pdrgpdrgpcrPart, m_ulSecondaryScanId, m_ppartcnstr, m_ppartcnstrRel, ulExpectedPartitionSelectors); }
//--------------------------------------------------------------------------- // @function: // CDatumBoolGPDB::CDatumBoolGPDB // // @doc: // Ctor // //--------------------------------------------------------------------------- CDatumBoolGPDB::CDatumBoolGPDB ( CSystemId sysid, BOOL fVal, BOOL fNull ) : m_fVal(fVal), m_fNull(fNull) { CMDAccessor *pmda = COptCtxt::PoctxtFromTLS()->Pmda(); IMDId *pmdid = dynamic_cast<const CMDTypeBoolGPDB *>(pmda->PtMDType<IMDTypeBool>(sysid))->Pmdid(); pmdid->AddRef(); m_pmdid = pmdid; if (FNull()) { // needed for hash computation m_fVal = false; } }
//--------------------------------------------------------------------------- // @function: // CDatumInt4GPDB::CDatumInt4GPDB // // @doc: // Ctor // //--------------------------------------------------------------------------- CDatumInt4GPDB::CDatumInt4GPDB ( CSystemId sysid, INT val, BOOL is_null ) : m_mdid(NULL), m_val(val), m_is_null(is_null) { CMDAccessor *md_accessor = COptCtxt::PoctxtFromTLS()->Pmda(); IMDId *mdid = dynamic_cast<const CMDTypeInt4GPDB *>(md_accessor->PtMDType<IMDTypeInt4>(sysid))->MDId(); mdid->AddRef(); m_mdid = mdid; if (IsNull()) { // needed for hash computation m_val = gpos::int_max; } }
//--------------------------------------------------------------------------- // @function: // CDatumInt4GPDB::CDatumInt4GPDB // // @doc: // Ctor // //--------------------------------------------------------------------------- CDatumInt4GPDB::CDatumInt4GPDB ( CSystemId sysid, INT iVal, BOOL fNull ) : m_pmdid(NULL), m_iVal(iVal), m_fNull(fNull) { CMDAccessor *pmda = COptCtxt::PoctxtFromTLS()->Pmda(); IMDId *pmdid = dynamic_cast<const CMDTypeInt4GPDB *>(pmda->PtMDType<IMDTypeInt4>(sysid))->Pmdid(); pmdid->AddRef(); m_pmdid = pmdid; if (FNull()) { // needed for hash computation m_iVal = INT_MAX; } }
//--------------------------------------------------------------------------- // @function: // CMDFunctionGPDB::PstrOutArgTypes // // @doc: // Serialize the array of output argument types into a comma-separated string // //--------------------------------------------------------------------------- CWStringDynamic * CMDFunctionGPDB::PstrOutArgTypes() const { GPOS_ASSERT(NULL != m_pdrgpmdidTypes); CWStringDynamic *pstr = GPOS_NEW(m_pmp) CWStringDynamic(m_pmp); const ULONG ulLen = m_pdrgpmdidTypes->UlLength(); for (ULONG ul = 0; ul < ulLen; ul++) { IMDId *pmdid = (*m_pdrgpmdidTypes)[ul]; if (ul == ulLen - 1) { // last element: do not print a comma pstr->AppendFormat(GPOS_WSZ_LIT("%ls"), pmdid->Wsz()); } else { pstr->AppendFormat(GPOS_WSZ_LIT("%ls%ls"), pmdid->Wsz(), CDXLTokens::PstrToken(EdxltokenComma)->Wsz()); } } return pstr; }
//--------------------------------------------------------------------------- // @function: // CPartitionPropagationSpec::FRequiresPartitionPropagation // // @doc: // Check if given part index id needs to be enforced on top of the given // expression // //--------------------------------------------------------------------------- BOOL CPartitionPropagationSpec::FRequiresPartitionPropagation ( IMemoryPool *mp, CExpression *pexpr, CExpressionHandle &exprhdl, ULONG part_idx_id ) const { GPOS_ASSERT(m_ppim->Contains(part_idx_id)); // construct partition propagation spec with the given id only, and check if it needs to be // enforced on top CPartIndexMap *ppim = GPOS_NEW(mp) CPartIndexMap(mp); IMDId *mdid = m_ppim->GetRelMdId(part_idx_id); CPartKeysArray *pdrgppartkeys = m_ppim->Pdrgppartkeys(part_idx_id); CPartConstraint *ppartcnstr = m_ppim->PpartcnstrRel(part_idx_id); UlongToPartConstraintMap *ppartcnstrmap = m_ppim->Ppartcnstrmap(part_idx_id); mdid->AddRef(); pdrgppartkeys->AddRef(); ppartcnstr->AddRef(); ppartcnstrmap->AddRef(); ppim->Insert(part_idx_id, ppartcnstrmap, m_ppim->Epim(part_idx_id), m_ppim->UlExpectedPropagators(part_idx_id), mdid, pdrgppartkeys, ppartcnstr); CPartitionPropagationSpec *ppps = GPOS_NEW(mp) CPartitionPropagationSpec(ppim, GPOS_NEW(mp) CPartFilterMap(mp)); CEnfdPartitionPropagation *pepp = GPOS_NEW(mp) CEnfdPartitionPropagation(ppps, CEnfdPartitionPropagation::EppmSatisfy, GPOS_NEW(mp) CPartFilterMap(mp)); CEnfdProp::EPropEnforcingType epetPartitionPropagation = pepp->Epet(exprhdl, CPhysical::PopConvert(pexpr->Pop()), true /*fPartitionPropagationRequired*/); pepp->Release(); return CEnfdProp::FEnforce(epetPartitionPropagation); }
//--------------------------------------------------------------------------- // @function: // CPartitionPropagationSpec::AppendEnforcers // // @doc: // Add required enforcers to dynamic array // //--------------------------------------------------------------------------- void CPartitionPropagationSpec::AppendEnforcers ( IMemoryPool *mp, CExpressionHandle &exprhdl, CReqdPropPlan * #ifdef GPOS_DEBUG prpp #endif // GPOS_DEBUG , CExpressionArray *pdrgpexpr, CExpression *pexpr ) { GPOS_ASSERT(NULL != prpp); GPOS_ASSERT(NULL != mp); GPOS_ASSERT(NULL != pdrgpexpr); GPOS_ASSERT(NULL != pexpr); ULongPtrArray *pdrgpul = m_ppim->PdrgpulScanIds(mp); const ULONG size = pdrgpul->Size(); for (ULONG ul = 0; ul < size; ul++) { ULONG scan_id = *((*pdrgpul)[ul]); GPOS_ASSERT(m_ppim->Contains(scan_id)); if (CPartIndexMap::EpimConsumer != m_ppim->Epim(scan_id) || 0 < m_ppim->UlExpectedPropagators(scan_id)) { continue; } if (!FRequiresPartitionPropagation(mp, pexpr, exprhdl, scan_id)) { continue; } CExpression *pexprResolver = NULL; IMDId *mdid = m_ppim->GetRelMdId(scan_id); CColRef2dArray *pdrgpdrgpcrKeys = NULL; CPartKeysArray *pdrgppartkeys = m_ppim->Pdrgppartkeys(scan_id); CPartConstraint *ppartcnstr = m_ppim->PpartcnstrRel(scan_id); UlongToPartConstraintMap *ppartcnstrmap = m_ppim->Ppartcnstrmap(scan_id); mdid->AddRef(); ppartcnstr->AddRef(); ppartcnstrmap->AddRef(); pexpr->AddRef(); // check if there is a predicate on this part index id UlongToExprMap *phmulexprEqFilter = GPOS_NEW(mp) UlongToExprMap(mp); UlongToExprMap *phmulexprFilter = GPOS_NEW(mp) UlongToExprMap(mp); CExpression *pexprResidual = NULL; if (m_ppfm->FContainsScanId(scan_id)) { CExpression *pexprScalar = PexprFilter(mp, scan_id); // find out which keys are used in the predicate, in case there are multiple // keys at this point (e.g. from a union of multiple CTE consumers) CColRefSet *pcrsUsed = CDrvdPropScalar::GetDrvdScalarProps(pexprScalar->PdpDerive())->PcrsUsed(); const ULONG ulKeysets = pdrgppartkeys->Size(); for (ULONG ulKey = 0; NULL == pdrgpdrgpcrKeys && ulKey < ulKeysets; ulKey++) { // get partition key CPartKeys *ppartkeys = (*pdrgppartkeys)[ulKey]; if (ppartkeys->FOverlap(pcrsUsed)) { pdrgpdrgpcrKeys = ppartkeys->Pdrgpdrgpcr(); } } // if we cannot find partition keys mapping the partition predicates, fall back to planner if (NULL == pdrgpdrgpcrKeys) { GPOS_RAISE(gpopt::ExmaGPOPT, gpopt::ExmiUnsatisfiedRequiredProperties); } pdrgpdrgpcrKeys->AddRef(); // split predicates and put them in the appropriate hashmaps SplitPartPredicates(mp, pexprScalar, pdrgpdrgpcrKeys, phmulexprEqFilter, phmulexprFilter, &pexprResidual); pexprScalar->Release(); } else { // doesn't matter which keys we use here since there is no filter GPOS_ASSERT(1 <= pdrgppartkeys->Size()); pdrgpdrgpcrKeys = (*pdrgppartkeys)[0]->Pdrgpdrgpcr(); pdrgpdrgpcrKeys->AddRef(); } pexprResolver = GPOS_NEW(mp) CExpression ( mp, GPOS_NEW(mp) CPhysicalPartitionSelector ( mp, scan_id, mdid, pdrgpdrgpcrKeys, ppartcnstrmap, ppartcnstr, phmulexprEqFilter, phmulexprFilter, pexprResidual ), pexpr ); pdrgpexpr->Append(pexprResolver); } pdrgpul->Release(); }
//--------------------------------------------------------------------------- // @function: // CPhysicalPartitionSelector::PppsRequired // // @doc: // Compute required partition propagation of the n-th child // //--------------------------------------------------------------------------- CPartitionPropagationSpec * CPhysicalPartitionSelector::PppsRequired ( IMemoryPool *mp, CExpressionHandle & exprhdl, CPartitionPropagationSpec *pppsRequired, ULONG #ifdef GPOS_DEBUG child_index #endif // GPOS_DEBUG , CDrvdProp2dArray *, //pdrgpdpCtxt, ULONG //ulOptReq ) { GPOS_ASSERT(0 == child_index); GPOS_ASSERT(NULL != pppsRequired); CPartIndexMap *ppimInput = pppsRequired->Ppim(); CPartFilterMap *ppfmInput = pppsRequired->Ppfm(); ULongPtrArray *pdrgpulInputScanIds = ppimInput->PdrgpulScanIds(mp); CPartIndexMap *ppim = GPOS_NEW(mp) CPartIndexMap(mp); CPartFilterMap *ppfm = GPOS_NEW(mp) CPartFilterMap(mp); CPartInfo *ppartinfo = exprhdl.GetRelationalProperties(0)->Ppartinfo(); const ULONG ulScanIds = pdrgpulInputScanIds->Size(); for (ULONG ul = 0; ul < ulScanIds; ul++) { ULONG scan_id = *((*pdrgpulInputScanIds)[ul]); ULONG ulExpectedPropagators = ppimInput->UlExpectedPropagators(scan_id); if (scan_id == m_scan_id) { // partition propagation resolved - do not need to require from children continue; } if (!ppartinfo->FContainsScanId(scan_id) && ppartinfo->FContainsScanId(m_scan_id)) { // dynamic scan for the required id not defined below, but the current one is: do not push request down continue; } IMDId *mdid = ppimInput->GetRelMdId(scan_id); CPartKeysArray *pdrgppartkeys = ppimInput->Pdrgppartkeys(scan_id); UlongToPartConstraintMap *ppartcnstrmap = ppimInput->Ppartcnstrmap(scan_id); CPartConstraint *ppartcnstr = ppimInput->PpartcnstrRel(scan_id); CPartIndexMap::EPartIndexManipulator epim = ppimInput->Epim(scan_id); mdid->AddRef(); pdrgppartkeys->AddRef(); ppartcnstrmap->AddRef(); ppartcnstr->AddRef(); ppim->Insert(scan_id, ppartcnstrmap, epim, ulExpectedPropagators, mdid, pdrgppartkeys, ppartcnstr); (void) ppfm->FCopyPartFilter(m_mp, scan_id, ppfmInput); } // cleanup pdrgpulInputScanIds->Release(); return GPOS_NEW(mp) CPartitionPropagationSpec(ppim, ppfm); }
//--------------------------------------------------------------------------- // @function: // CXformImplementPartitionSelector::Transform // // @doc: // Actual transformation // //--------------------------------------------------------------------------- void CXformImplementPartitionSelector::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(); // extract components CLogicalPartitionSelector *popSelector = CLogicalPartitionSelector::PopConvert(pexpr->Pop()); CExpression *pexprRelational = (*pexpr)[0]; IMDId *pmdid = popSelector->Pmdid(); // addref all components pexprRelational->AddRef(); pmdid->AddRef(); HMUlExpr *phmulexprFilter = GPOS_NEW(pmp) HMUlExpr(pmp); const ULONG ulLevels = popSelector->UlPartLevels(); for (ULONG ul = 0; ul < ulLevels; ul++) { CExpression *pexprFilter = popSelector->PexprPartFilter(ul); GPOS_ASSERT(NULL != pexprFilter); pexprFilter->AddRef(); #ifdef GPOS_DEBUG BOOL fInserted = #endif phmulexprFilter->FInsert(GPOS_NEW(pmp) ULONG(ul), pexprFilter); GPOS_ASSERT(fInserted); } // assemble physical operator CPhysicalPartitionSelectorDML *popPhysicalPartitionSelector = GPOS_NEW(pmp) CPhysicalPartitionSelectorDML ( pmp, pmdid, phmulexprFilter, popSelector->PcrOid() ); CExpression *pexprPartitionSelector = GPOS_NEW(pmp) CExpression ( pmp, popPhysicalPartitionSelector, pexprRelational ); // add alternative to results pxfres->Add(pexprPartitionSelector); }
//--------------------------------------------------------------------------- // @function: // CPhysicalPartitionSelector::PppsRequired // // @doc: // Compute required partition propagation of the n-th child // //--------------------------------------------------------------------------- CPartitionPropagationSpec * CPhysicalPartitionSelector::PppsRequired ( IMemoryPool *pmp, CExpressionHandle & exprhdl, CPartitionPropagationSpec *pppsRequired, ULONG #ifdef GPOS_DEBUG ulChildIndex #endif // GPOS_DEBUG , DrgPdp *, //pdrgpdpCtxt, ULONG //ulOptReq ) { GPOS_ASSERT(0 == ulChildIndex); GPOS_ASSERT(NULL != pppsRequired); CPartIndexMap *ppimInput = pppsRequired->Ppim(); CPartFilterMap *ppfmInput = pppsRequired->Ppfm(); DrgPul *pdrgpulInputScanIds = ppimInput->PdrgpulScanIds(pmp); CPartIndexMap *ppim = GPOS_NEW(pmp) CPartIndexMap(pmp); CPartFilterMap *ppfm = GPOS_NEW(pmp) CPartFilterMap(pmp); CPartInfo *ppartinfo = exprhdl.Pdprel(0)->Ppartinfo(); const ULONG ulScanIds = pdrgpulInputScanIds->UlLength(); for (ULONG ul = 0; ul < ulScanIds; ul++) { ULONG ulScanId = *((*pdrgpulInputScanIds)[ul]); ULONG ulExpectedPropagators = ppimInput->UlExpectedPropagators(ulScanId); if (ulScanId == m_ulScanId) { // partition propagation resolved - do not need to require from children continue; } if (!ppartinfo->FContainsScanId(ulScanId) && ppartinfo->FContainsScanId(m_ulScanId)) { // dynamic scan for the required id not defined below, but the current one is: do not push request down continue; } IMDId *pmdid = ppimInput->PmdidRel(ulScanId); DrgPpartkeys *pdrgppartkeys = ppimInput->Pdrgppartkeys(ulScanId); PartCnstrMap *ppartcnstrmap = ppimInput->Ppartcnstrmap(ulScanId); CPartConstraint *ppartcnstr = ppimInput->PpartcnstrRel(ulScanId); CPartIndexMap::EPartIndexManipulator epim = ppimInput->Epim(ulScanId); pmdid->AddRef(); pdrgppartkeys->AddRef(); ppartcnstrmap->AddRef(); ppartcnstr->AddRef(); ppim->Insert(ulScanId, ppartcnstrmap, epim, ulExpectedPropagators, pmdid, pdrgppartkeys, ppartcnstr); (void) ppfm->FCopyPartFilter(m_pmp, ulScanId, ppfmInput); } // cleanup pdrgpulInputScanIds->Release(); return GPOS_NEW(pmp) CPartitionPropagationSpec(ppim, ppfm); }