CATCH_NEXTROW()
 {
     ActivityTimer t(totalCycles, timeActivities);
     if (abortSoon || eof)
         return NULL;
     RtlDynamicRowBuilder out(queryRowAllocator());
     size32_t sz = helper->clearAggregate(out);
     OwnedConstThorRow row = input->nextRow();
     if (row)
     {
         sz = helper->processFirst(out, row);
         // NB: if ungrouped existsAggregate, no need to look at rest of input
         if (!ungroupedExistsAggregate)
         {
             while (!abortSoon)
             {
                 row.setown(input->nextRow());
                 if (!row)
                     break;
                 sz = helper->processNext(out, row);
             }
         }
         if (!input->isGrouped())
             eof = true;
     }
     else
     {
         eof = true;
         if (input->isGrouped())
             return NULL;
     }
     dataLinkIncrement();
     return out.finalizeRowClear(sz);
 }
 CATCH_NEXTROW()
 {
     ActivityTimer t(totalCycles, timeActivities);
     while(!abortSoon)
     {
         OwnedConstThorRow row = input->nextRow();
         if(!row)    {
             numToSkip = whichSample ? whichSample - 1 : 0;
             if(anyThisGroup) {
                 anyThisGroup = false;           
                 break;
             }
             row.setown(input->nextRow());
             if(!row) 
                 break;
         }
         if(numToSkip == 0) {
             anyThisGroup = true;
             numToSkip = numSamples - 1;
             dataLinkIncrement();
             return row.getClear();
         }
         numToSkip--;
     }
     return NULL;
 }