code: func (gbi *groupByIterator) nextAtIdx(i int) {
  	// loop until we find a non-empty row. This is an optimization - the loop and if/break can be removed.
  	for {
  		nr, rowID, wrapped := gbi.rowIters[i].Next()
  		if nr == nil {
  			gbi.done = true
  			return
  		}
  		if wrapped && i != 0 {
  			gbi.nextAtIdx(i - 1)
  		}
  		if i == 0 && gbi.filter != nil {
  			gbi.rows[i].row = nr.Intersect(gbi.filter)
  		} else if i == 0 || i == len(gbi.rows)-1 {
  			gbi.rows[i].row = nr
  		} else {
  			gbi.rows[i].row = nr.Intersect(gbi.rows[i-1].row)
  		}
  		gbi.rows[i].id = rowID
  
  		if !gbi.rows[i].row.IsEmpty() {
  			break
  		}
  	}
  }
docs: // nextAtIdx is a recursive helper method for getting the next row for the field
  // at index i, and then updating the rows in the "higher" fields if it wraps.