diff --git a/cassandra_test.go b/cassandra_test.go index b4cd3bbfb..f7539ded4 100644 --- a/cassandra_test.go +++ b/cassandra_test.go @@ -419,6 +419,11 @@ func TestPagingWithAllowFiltering(t *testing.T) { for { iter := qry.PageState(currentPageState).Iter() + + // Here we make sure that all iterator, but last one have some data in it + if !iter.LastPage() && iter.NumRows() == 0 { + t.Errorf("expected at least one row, but got 0") + } for iter.Scan(&c1, &f1) { if c1 != f1 { t.Fatalf("expected c1 and f1 values to be the same, but got c1=%d f1=%d", c1, f1) @@ -428,10 +433,13 @@ func TestPagingWithAllowFiltering(t *testing.T) { if err := iter.Close(); err != nil { t.Fatal("select:", err.Error()) } - newPageState := iter.PageState() - if len(newPageState) == 0 || len(currentPageState) == len(newPageState) && bytes.Compare(newPageState, currentPageState) == 0 { + if iter.LastPage() { break } + newPageState := iter.PageState() + if len(currentPageState) == len(newPageState) && bytes.Compare(newPageState, currentPageState) == 0 { + t.Fatalf("page state did not change") + } currentPageState = newPageState } @@ -2355,7 +2363,7 @@ func TestManualQueryPaging(t *testing.T) { fetched++ } - if len(iter.PageState()) > 0 { + if !iter.LastPage() { // more pages iter = query.PageState(iter.PageState()).Iter() } else { diff --git a/session.go b/session.go index b553d154d..2b72e6988 100644 --- a/session.go +++ b/session.go @@ -1393,9 +1393,24 @@ func (q *Query) Iter() *Iter { if isUseStatement(q.stmt) { return &Iter{err: ErrUseStmt} } - // if the query was specifically run on a connection then re-use that - // connection when fetching the next results + + if !q.disableAutoPage { + return q.executeQuery() + } + + // Retry on empty page if pagination is manual + iter := q.executeQuery() + for iter.err == nil && iter.numRows == 0 && !iter.LastPage() { + q.PageState(iter.PageState()) + iter = q.executeQuery() + } + return iter +} + +func (q *Query) executeQuery() *Iter { if q.conn != nil { + // if the query was specifically run on a connection then re-use that + // connection when fetching the next results return q.conn.executeQuery(q.Context(), q) } return q.session.executeQuery(q) @@ -1771,6 +1786,11 @@ func (iter *Iter) PageState() []byte { return iter.meta.pagingState } +// LastPage returns true if there are no more pages to fetch. +func (iter *Iter) LastPage() bool { + return len(iter.meta.pagingState) == 0 +} + // NumRows returns the number of rows in this pagination, it will update when new // pages are fetched, it is not the value of the total number of rows this iter // will return unless there is only a single page returned.