//--------------------------------------------------------------------------- // @function: // CBinding::PexprExtract // // @doc: // Extract a binding according to a given pattern; // Keep root node fixed; // //--------------------------------------------------------------------------- CExpression * CBinding::PexprExtract ( IMemoryPool *pmp, CGroupExpression *pgexpr, CExpression *pexprPattern, CExpression *pexprLast ) { GPOS_CHECK_ABORT; if (!pexprPattern->FMatchPattern(pgexpr)) { // shallow matching fails return NULL; } // the previously extracted pattern must have the same root GPOS_ASSERT_IMP(NULL != pexprLast, pexprLast->Pgexpr() == pgexpr); COperator *popPattern = pexprPattern->Pop(); if (popPattern->FPattern() && CPattern::PopConvert(popPattern)->FLeaf()) { // return immediately; no deep extraction for leaf patterns pgexpr->Pop()->AddRef(); return GPOS_NEW(pmp) CExpression(pmp, pgexpr->Pop(), pgexpr); } DrgPexpr *pdrgpexpr = NULL; ULONG ulArity = pgexpr->UlArity(); if (0 == ulArity && NULL != pexprLast) { // no more bindings return NULL; } else { // attempt binding to children pdrgpexpr = GPOS_NEW(pmp) DrgPexpr(pmp); if (!FExtractChildren(pmp, pgexpr, pexprPattern, pexprLast, pdrgpexpr)) { pdrgpexpr->Release(); return NULL; } } CExpression *pexpr = PexprFinalize(pmp, pgexpr, pdrgpexpr); GPOS_ASSERT(NULL != pexpr); return pexpr; }
//--------------------------------------------------------------------------- // @function: // CBinding::PexprExtract // // @doc: // Extract a binding according to a given pattern; // If no appropriate child pattern can be matched advance the root node // until group is exhausted; // //--------------------------------------------------------------------------- CExpression * CBinding::PexprExtract ( IMemoryPool *pmp, CGroup *pgroup, CExpression *pexprPattern, CExpression *pexprLast ) { GPOS_CHECK_STACK_SIZE; GPOS_CHECK_ABORT; GPOS_ASSERT(NULL != pgroup); GPOS_ASSERT(NULL != pexprPattern); CGroupExpression *pgexpr = NULL; if (NULL != pexprLast) { pgexpr = pexprLast->Pgexpr(); } else { // init cursor pgexpr = PgexprNext(pgroup, NULL); } GPOS_ASSERT(NULL != pgexpr); COperator *popPattern = pexprPattern->Pop(); if (popPattern->FPattern() && CPattern::PopConvert(popPattern)->FLeaf()) { // for leaf patterns, we do not iterate on group expressions if (NULL != pexprLast) { // if a leaf was extracted before, then group is exhausted return NULL; } return PexprExtract(pmp, pgexpr, pexprPattern, pexprLast); } // start position for next binding CExpression *pexprStart = pexprLast; do { if (pexprPattern->FMatchPattern(pgexpr)) { CExpression *pexprResult = PexprExtract(pmp, pgexpr, pexprPattern, pexprStart); if (NULL != pexprResult) { return pexprResult; } } // move cursor and reset start position pgexpr = PgexprNext(pgroup, pgexpr); pexprStart = NULL; GPOS_CHECK_ABORT; } while (NULL != pgexpr); // group exhausted return NULL; }