'Helper method for fetchone, which returns the next row from a buffer.
If the buffer is empty, attempts to paginate through the result set for
the next page, and load it into the buffer.'

def next(self):

    if (not self.job_id):
        return None
    if (len(self.buffer) == 0):
        if self.all_pages_loaded:
            return None
        query_results = self.service.jobs().getQueryResults(projectId=self.project_id, jobId=self.job_id, pageToken=self.page_token).execute()
        if (('rows' in query_results) and query_results['rows']):
            self.page_token = query_results.get('pageToken')
            fields = query_results['schema']['fields']
            col_types = [field['type'] for field in fields]
            rows = query_results['rows']
            for dict_row in rows:
                typed_row = [_bq_cast(vs['v'], col_types[idx]) for (idx, vs) in enumerate(dict_row['f'])]
                self.buffer.append(typed_row)
            if (not self.page_token):
                self.all_pages_loaded = True
        else:
            self.page_token = None
            self.job_id = None
            self.page_token = None
            return None
    return self.buffer.pop(0)
