Skip to content

Commit

Permalink
Make Query.Iter to skip through empty iters when pagining is manual
Browse files Browse the repository at this point in the history
In some cases it confuses user to have no rows in the iterator.
This simple solution makes Query.Iter to retry on empty iterator.
  • Loading branch information
dkropachev committed Jul 8, 2024
1 parent bc4e3a3 commit c212c76
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 5 deletions.
14 changes: 11 additions & 3 deletions cassandra_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
}

Expand Down Expand Up @@ -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 {
Expand Down
24 changes: 22 additions & 2 deletions session.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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.
Expand Down

0 comments on commit c212c76

Please sign in to comment.