Skip to content

Commit 1867bd3

Browse files
author
enikon
authored
OAS-10935 Get Raw JSON bytes from query cursor (#683)
1 parent ea2f3ab commit 1867bd3

File tree

4 files changed

+113
-6
lines changed

4 files changed

+113
-6
lines changed

v2/arangodb/cursor.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ package arangodb
2323
import (
2424
"context"
2525
"io"
26+
27+
"github.com/arangodb/go-driver/v2/connection"
2628
)
2729

2830
// Cursor is returned from a query, used to iterate over a list of documents.
@@ -77,6 +79,14 @@ type CursorBatch interface {
7779
// E.g. `var result []MyStruct{}`.
7880
RetryReadBatch(ctx context.Context, result interface{}) error
7981

82+
// ReadNextRawBatch reads the next batch of documents from the cursor.
83+
// The result must be a pointer to a byte array *[]bytes.
84+
ReadNextRawBatch(ctx context.Context, result *connection.RawObject) error
85+
86+
// RetryReadRawBatch retries the last batch read made by ReadNextRawBatch.
87+
// The result must be a pointer to a byte array *[]bytes.
88+
RetryReadRawBatch(ctx context.Context, result *connection.RawObject) error
89+
8090
// Count returns the total number of result documents available.
8191
// A valid return value is only available when the cursor has been created with `Count` and not with `Stream`.
8292
Count() int64

v2/arangodb/cursor_impl.go

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -115,22 +115,37 @@ func (c *cursor) ReadDocument(ctx context.Context, result interface{}) (Document
115115
return c.readDocument(ctx, result)
116116
}
117117

118-
func (c *cursor) ReadNextBatch(ctx context.Context, result interface{}) error {
119-
err := c.getNextBatch(ctx, "")
118+
func (c *cursor) readBatch(ctx context.Context, result interface{}, retryBatchID string) error {
119+
err := c.getNextBatch(ctx, retryBatchID)
120120
if err != nil {
121121
return err
122122
}
123-
124123
return json.Unmarshal(c.data.Result.in, result)
125124
}
126125

127-
func (c *cursor) RetryReadBatch(ctx context.Context, result interface{}) error {
128-
err := c.getNextBatch(ctx, c.retryData.currentBatchID)
126+
func (c *cursor) readRawBatch(ctx context.Context, result *connection.RawObject, retryBatchID string) error {
127+
err := c.getNextBatch(ctx, retryBatchID)
129128
if err != nil {
130129
return err
131130
}
131+
*result = append([]byte(nil), c.data.Result.in...)
132+
return nil
133+
}
132134

133-
return json.Unmarshal(c.data.Result.in, result)
135+
func (c *cursor) ReadNextBatch(ctx context.Context, result interface{}) error {
136+
return c.readBatch(ctx, result, "")
137+
}
138+
139+
func (c *cursor) RetryReadBatch(ctx context.Context, result interface{}) error {
140+
return c.readBatch(ctx, result, c.retryData.currentBatchID)
141+
}
142+
143+
func (c *cursor) ReadNextRawBatch(ctx context.Context, result *connection.RawObject) error {
144+
return c.readRawBatch(ctx, result, "")
145+
}
146+
147+
func (c *cursor) RetryReadRawBatch(ctx context.Context, result *connection.RawObject) error {
148+
return c.readRawBatch(ctx, result, c.retryData.currentBatchID)
134149
}
135150

136151
func (c *cursor) readDocument(ctx context.Context, result interface{}) (DocumentMeta, error) {

v2/connection/connection.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,3 +148,7 @@ type Response interface {
148148

149149
RawResponse() *http.Response
150150
}
151+
152+
// RawObject is a raw encoded object.
153+
// Connection implementations must be able to unmarshal *RawObject into Go objects.
154+
type RawObject []byte

v2/tests/cursor_test.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2025 ArangoDB GmbH, Cologne, Germany
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
// Copyright holder is ArangoDB GmbH, Cologne, Germany
19+
//
20+
21+
package tests
22+
23+
import (
24+
"context"
25+
"fmt"
26+
"testing"
27+
28+
"github.com/arangodb/go-driver/v2/arangodb"
29+
"github.com/arangodb/go-driver/v2/connection"
30+
"github.com/stretchr/testify/require"
31+
)
32+
33+
// Test_ExplainQuery tries to explain several AQL queries.
34+
func Test_CursorRawResult(t *testing.T) {
35+
Wrap(t, func(t *testing.T, client arangodb.Client) {
36+
WithDatabase(t, client, nil, func(db arangodb.Database) {
37+
WithCollectionV2(t, db, nil, func(col arangodb.Collection) {
38+
WithUserDocs(t, col, func(docs []UserDoc) {
39+
withContextT(t, defaultTestTimeout, func(ctx context.Context, tb testing.TB) {
40+
skipBelowVersion(client, ctx, "3.11", t)
41+
42+
query := fmt.Sprintf("FOR d IN `%s` SORT d.Title RETURN d", col.Name())
43+
44+
t.Run("Test retry read when reading raw JSON batch", func(t *testing.T) {
45+
opts := arangodb.QueryOptions{
46+
Count: true,
47+
BatchSize: 2,
48+
Options: arangodb.QuerySubOptions{
49+
AllowRetry: true,
50+
},
51+
}
52+
53+
cursor, err := db.QueryBatch(ctx, query, &opts, nil)
54+
require.NoError(t, err)
55+
for {
56+
if !cursor.HasMoreBatches() {
57+
break
58+
}
59+
var result connection.RawObject
60+
require.NoError(t, cursor.ReadNextRawBatch(ctx, &result))
61+
62+
var resultRetry connection.RawObject
63+
require.NoError(t, cursor.RetryReadRawBatch(ctx, &resultRetry))
64+
65+
require.Equal(t, len(result), len(resultRetry))
66+
require.Equal(t, result, resultRetry)
67+
68+
}
69+
70+
err = cursor.Close()
71+
require.NoError(t, err)
72+
})
73+
})
74+
})
75+
})
76+
})
77+
})
78+
}

0 commit comments

Comments
 (0)