Skip to content

Commit

Permalink
Fix multi-query resultset iteration
Browse files Browse the repository at this point in the history
This uses an ugly hack to keep the standard rows iterator from closing the
HTTP body when it reaches the end: It sets the body to nil.

I think there's room now to consolidate the `rows` and `multiQueriesRows`.
My initial thought was to expand `rows`, but now that I have two
implementations, I believe it would make more sense instead to consolidate
everything in to `multiQueriesRows`.  It already has a few special cases
anyway.
  • Loading branch information
flimzy committed May 2, 2020
1 parent aceb540 commit b0a1306
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 9 deletions.
53 changes: 44 additions & 9 deletions db_live_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,51 @@ func TestQueries_1_x(t *testing.T) {
}
}

// func TestQueries_2_x(t *testing.T) {
// dsn := os.Getenv("KIVIK_TEST_DSN_COUCH23")
// if dsn == "" {
// dsn = os.Getenv("KIVIK_TEST_DSN_COUCH22")
// }
// if dsn == "" {
// t.Skip("Neither KIVIK_TEST_DSN_COUCH22 nor KIVIK_TEST_DSN_COUCH23 configured")
// }
func TestQueries_2_x(t *testing.T) {
dsn := os.Getenv("KIVIK_TEST_DSN_COUCH23")
if dsn == "" {
dsn = os.Getenv("KIVIK_TEST_DSN_COUCH22")
}
if dsn == "" {
t.Skip("Neither KIVIK_TEST_DSN_COUCH22 nor KIVIK_TEST_DSN_COUCH23 configured")
}

// }
client, err := kivik.New("couch", dsn)
if err != nil {
t.Fatal(err)
}

db := client.DB(context.Background(), "_users")
rows, err := db.AllDocs(context.Background(), map[string]interface{}{
"queries": []map[string]interface{}{
{},
{},
},
})
if err != nil {
t.Fatal(err)
}
defer rows.Close() // nolint:errcheck
result := make([]interface{}, 0)
for rows.Next() {
if rows.EOQ() {
result = append(result, map[string]interface{}{
"EOQ": true,
"total_rows": rows.TotalRows(),
})
continue
}
result = append(result, map[string]interface{}{
"_id": rows.ID(),
})
}
if err := rows.Err(); err != nil {
t.Fatal(err)
}
if d := testy.DiffInterface(testy.Snapshot(t), result); d != nil {
t.Error(d)
}
}

// func TestQueries_3_x(t *testing.T) {
// dsn := os.Getenv("KIVIK_TEST_DSN_COUCH30")
Expand Down
4 changes: 4 additions & 0 deletions iter.go
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,10 @@ func (i *iter) nextRow(row interface{}) error {

func (i *iter) Close() error {
atomic.StoreInt32(&i.closed, 1)
// body will be nil if we're iterating over a multi-query resultset.
if i.body == nil {
return nil
}
return i.body.Close()
}

Expand Down
3 changes: 3 additions & 0 deletions rows.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ func (r *multiQueriesRows) begin() error {
Closer: r.r,
}
r.rows = newRows(r.ctx, in).(*rows)
r.rows.body = nil
r.rows.dec = json.NewDecoder(in)
return r.rows.begin()
}
Expand All @@ -223,6 +224,7 @@ func (r *multiQueriesRows) begin() error {
return err
}
r.rows = newRows(r.ctx, r.r).(*rows)
r.rows.body = nil
r.rows.iter.dec = r.dec
return r.rows.iter.begin()
}
Expand All @@ -249,6 +251,7 @@ func (r *multiQueriesRows) nextQuery() error {
}
r.queryIndex++
r.rows = rows
r.rows.body = nil
return nil
}

Expand Down
16 changes: 16 additions & 0 deletions testdata/TestQueries_2_x
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
([]interface {}) (len=4) {
(map[string]interface {}) (len=1) {
(string) (len=3) "_id": (string) (len=13) "_design/_auth"
},
(map[string]interface {}) (len=2) {
(string) (len=3) "EOQ": (bool) true,
(string) (len=10) "total_rows": (int64) 1
},
(map[string]interface {}) (len=1) {
(string) (len=3) "_id": (string) (len=13) "_design/_auth"
},
(map[string]interface {}) (len=2) {
(string) (len=3) "EOQ": (bool) true,
(string) (len=10) "total_rows": (int64) 1
}
}

0 comments on commit b0a1306

Please sign in to comment.