//--------------------------------------------------------------------------- // @function: // CBinding::FAdvanceChildCursors // // @doc: // Advance cursors of child expressions and populate the given array // with the next child expressions // //--------------------------------------------------------------------------- BOOL CBinding::FAdvanceChildCursors ( IMemoryPool *pmp, CGroupExpression *pgexpr, CExpression *pexprPattern, CExpression *pexprLast, DrgPexpr *pdrgpexpr ) { GPOS_ASSERT(NULL != pexprPattern); GPOS_ASSERT(NULL != pdrgpexpr); const ULONG ulArity = pgexpr->UlArity(); if (NULL == pexprLast) { // first call, initialize cursors return FInitChildCursors(pmp, pgexpr, pexprPattern, pdrgpexpr); } // could we advance a child's cursor? BOOL fCursorAdvanced = false; // number of exhausted cursors ULONG ulExhaustedCursors = 0; for (ULONG ul = 0; ul < ulArity; ul++) { CGroup *pgroup = (*pgexpr)[ul]; CExpression *pexprPatternChild = PexprExpandPattern(pexprPattern, ul, ulArity); CExpression *pexprNewChild = NULL; if (fCursorAdvanced) { // re-use last extracted child expression (*pexprLast)[ul]->AddRef(); pexprNewChild = (*pexprLast)[ul]; } else { CExpression *pexprLastChild = (*pexprLast)[ul]; GPOS_ASSERT(pgroup == pexprLastChild->Pgexpr()->Pgroup()); // advance current cursor pexprNewChild = PexprExtract(pmp, pgroup, pexprPatternChild, pexprLastChild); if (NULL == pexprNewChild) { // cursor is exhausted, we need to reset it pexprNewChild = PexprExtract(pmp, pgroup, pexprPatternChild, NULL /*pexprLastChild*/); ulExhaustedCursors++; } else { // advancing current cursor has succeeded fCursorAdvanced = true; } } GPOS_ASSERT(NULL != pexprNewChild); pdrgpexpr->Append(pexprNewChild); } GPOS_ASSERT(ulExhaustedCursors <= ulArity); return ulExhaustedCursors < ulArity; }