Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions test/on_failure.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/bin/bash
exit 1
echo "failure!\n"

echo "\nARANGODB-STARTER logs: "
Expand Down
1 change: 1 addition & 0 deletions v2/arangodb/collection_documents_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ type CollectionDocumentCreate interface {
}

type CollectionDocumentCreateResponseReader interface {
shared.ReadAllReadable[CollectionDocumentCreateResponse]
Read() (CollectionDocumentCreateResponse, error)
}

Expand Down
2 changes: 2 additions & 0 deletions v2/arangodb/collection_documents_create_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ func newCollectionDocumentCreateResponseReader(array *connection.Array, options
c.response.New = newUnmarshalInto(c.options.NewObject)
}

c.ReadAllReader = shared.ReadAllReader[CollectionDocumentCreateResponse, *collectionDocumentCreateResponseReader]{Reader: c}
return c
}

Expand All @@ -147,6 +148,7 @@ type collectionDocumentCreateResponseReader struct {
Old *UnmarshalInto `json:"old,omitempty"`
New *UnmarshalInto `json:"new,omitempty"`
}
shared.ReadAllReader[CollectionDocumentCreateResponse, *collectionDocumentCreateResponseReader]
}

func (c *collectionDocumentCreateResponseReader) Read() (CollectionDocumentCreateResponse, error) {
Expand Down
2 changes: 2 additions & 0 deletions v2/arangodb/collection_documents_delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ type CollectionDocumentDeleteResponse struct {
}

type CollectionDocumentDeleteResponseReader interface {
shared.ReadAllIntoReadable[CollectionDocumentDeleteResponse]
Read(i interface{}) (CollectionDocumentDeleteResponse, error)
}

Expand All @@ -82,6 +83,7 @@ type CollectionDocumentDeleteOptions struct {
WithWaitForSync *bool

// Return additionally the complete previous revision of the changed document
// Should be a pointer to an object
OldObject interface{}

// If set to true, an empty object is returned as response if the document operation succeeds.
Expand Down
3 changes: 3 additions & 0 deletions v2/arangodb/collection_documents_delete_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ var _ CollectionDocumentDelete = &collectionDocumentDelete{}

type collectionDocumentDelete struct {
collection *collection
shared.ReadAllIntoReader[CollectionDocumentDeleteResponse, *collectionDocumentDeleteResponseReader]
}

func (c collectionDocumentDelete) DeleteDocument(ctx context.Context, key string) (CollectionDocumentDeleteResponse, error) {
Expand Down Expand Up @@ -103,6 +104,7 @@ func (c collectionDocumentDelete) DeleteDocumentsWithOptions(ctx context.Context
func newCollectionDocumentDeleteResponseReader(array *connection.Array, options *CollectionDocumentDeleteOptions) *collectionDocumentDeleteResponseReader {
c := &collectionDocumentDeleteResponseReader{array: array, options: options}

c.ReadAllIntoReader = shared.ReadAllIntoReader[CollectionDocumentDeleteResponse, *collectionDocumentDeleteResponseReader]{Reader: c}
return c
}

Expand All @@ -111,6 +113,7 @@ var _ CollectionDocumentDeleteResponseReader = &collectionDocumentDeleteResponse
type collectionDocumentDeleteResponseReader struct {
array *connection.Array
options *CollectionDocumentDeleteOptions
shared.ReadAllIntoReader[CollectionDocumentDeleteResponse, *collectionDocumentDeleteResponseReader]
}

func (c *collectionDocumentDeleteResponseReader) Read(i interface{}) (CollectionDocumentDeleteResponse, error) {
Expand Down
1 change: 1 addition & 0 deletions v2/arangodb/collection_documents_read.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ type CollectionDocumentRead interface {

type CollectionDocumentReadResponseReader interface {
Read(i interface{}) (CollectionDocumentReadResponse, error)
shared.ReadAllIntoReadable[CollectionDocumentReadResponse]
}

type CollectionDocumentReadResponse struct {
Expand Down
3 changes: 2 additions & 1 deletion v2/arangodb/collection_documents_read_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ func (c collectionDocumentRead) ReadDocumentWithOptions(ctx context.Context, key

func newCollectionDocumentReadResponseReader(array *connection.Array, options *CollectionDocumentReadOptions) *collectionDocumentReadResponseReader {
c := &collectionDocumentReadResponseReader{array: array, options: options}

c.ReadAllIntoReader = shared.ReadAllIntoReader[CollectionDocumentReadResponse, *collectionDocumentReadResponseReader]{Reader: c}
return c
}

Expand All @@ -106,6 +106,7 @@ var _ CollectionDocumentReadResponseReader = &collectionDocumentReadResponseRead
type collectionDocumentReadResponseReader struct {
array *connection.Array
options *CollectionDocumentReadOptions
shared.ReadAllIntoReader[CollectionDocumentReadResponse, *collectionDocumentReadResponseReader]
}

func (c *collectionDocumentReadResponseReader) Read(i interface{}) (CollectionDocumentReadResponse, error) {
Expand Down
99 changes: 99 additions & 0 deletions v2/arangodb/shared/read_all.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
//
// DISCLAIMER
//
// Copyright 2017-2025 ArangoDB GmbH, Cologne, Germany
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Copyright holder is ArangoDB GmbH, Cologne, Germany
//

package shared

import (
"errors"
"reflect"
)

type readReader[T any] interface {
Read() (T, error)
}

type ReadAllReadable[T any] interface {
ReadAll() ([]T, []error)
}

type ReadAllReader[T any, R readReader[T]] struct {
Reader R
}

func (r ReadAllReader[T, R]) ReadAll() ([]T, []error) {
var docs []T
var errs []error
for {
doc, e := r.Reader.Read()
if errors.Is(e, NoMoreDocumentsError{}) {
break
}
errs = append(errs, e)
docs = append(docs, doc)
}
return docs, errs
}

type readReaderInto[T any] interface {
Read(i interface{}) (T, error)
}

type ReadAllIntoReadable[T any] interface {
ReadAll(i interface{}) ([]T, []error)
}

type ReadAllIntoReader[T any, R readReaderInto[T]] struct {
Reader R
}

func (r ReadAllIntoReader[T, R]) ReadAll(i interface{}) ([]T, []error) {

iVal := reflect.ValueOf(i)
if iVal.Kind() != reflect.Ptr || iVal.Elem().Kind() != reflect.Slice {
panic("i must be a pointer to a slice")
}

eVal := iVal.Elem()
eType := eVal.Type().Elem()

var docs []T
var errs []error

for {
res := reflect.New(eType)
doc, e := r.Reader.Read(res.Interface())
if errors.Is(e, NoMoreDocumentsError{}) {
break
}

iDocVal := reflect.ValueOf(doc)
if iDocVal.Kind() == reflect.Ptr {
iDocVal = iDocVal.Elem()
}
docCopy := reflect.New(iDocVal.Type()).Elem()
docCopy.Set(iDocVal)

errs = append(errs, e)
docs = append(docs, docCopy.Interface().(T))
eVal = reflect.Append(eVal, res.Elem())
}
iVal.Elem().Set(eVal)
return docs, errs
}
138 changes: 95 additions & 43 deletions v2/tests/database_collection_doc_create_code_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,10 @@ import (
"context"
"testing"

"github.com/arangodb/go-driver/v2/arangodb/shared"

"github.com/stretchr/testify/require"

"github.com/arangodb/go-driver/v2/arangodb"
"github.com/arangodb/go-driver/v2/arangodb/shared"
)

type DocWithCode struct {
Expand All @@ -38,66 +37,119 @@ type DocWithCode struct {

func Test_DatabaseCollectionDocCreateCode(t *testing.T) {
Wrap(t, func(t *testing.T, client arangodb.Client) {
// COMMENTED OUT FOR DEBUGGING ONLY
// WithDatabase(t, client, nil, func(db arangodb.Database) {
// WithCollectionV2(t, db, nil, func(col arangodb.Collection) {
// withContextT(t, defaultTestTimeout, func(ctx context.Context, tb testing.TB) {
// doc := DocWithCode{
// Key: "test",
// }

// meta, err := col.CreateDocumentWithOptions(ctx, doc, &arangodb.CollectionDocumentCreateOptions{})
// require.NoError(t, err)
// require.NotEmpty(t, meta.Rev)
// require.Empty(t, meta.Old)
// require.Empty(t, meta.New)

// rdoc, err := col.ReadDocument(ctx, "test", &doc)
// require.NoError(t, err)

// require.EqualValues(t, "test", rdoc.Key)
// })
// })
// })

// WithDatabase(t, client, nil, func(db arangodb.Database) {
// WithCollectionV2(t, db, nil, func(col arangodb.Collection) {
// withContextT(t, defaultTestTimeout, func(ctx context.Context, tb testing.TB) {
// doc := DocWithCode{
// Key: "test",
// }
// doc2 := DocWithCode{
// Key: "test2",
// }

// _, err := col.CreateDocuments(ctx, []any{
// doc, doc2,
// })
// require.NoError(t, err)

// docs, err := col.ReadDocuments(ctx, []string{
// "test",
// "tz44",
// "test2",
// })
// require.NoError(t, err)

// var z DocWithCode

// meta, err := docs.Read(&z)
// require.NoError(t, err)
// require.Equal(t, "test", meta.Key)

// _, err = docs.Read(&z)
// require.Error(t, err)
// require.True(t, shared.IsNotFound(err))

// meta, err = docs.Read(&z)
// require.NoError(t, err)
// require.Equal(t, "test2", meta.Key)

// _, err = docs.Read(&z)
// require.Error(t, err)
// require.True(t, shared.IsNoMoreDocuments(err))
// })
// })
// })

WithDatabase(t, client, nil, func(db arangodb.Database) {
WithCollectionV2(t, db, nil, func(col arangodb.Collection) {
withContextT(t, defaultTestTimeout, func(ctx context.Context, tb testing.TB) {
doc := DocWithCode{
Key: "test",
doc1 := DocWithCode{
Key: "test",
Code: "code1",
}
doc2 := DocWithCode{
Key: "test2",
Code: "code2",
}

meta, err := col.CreateDocumentWithOptions(ctx, doc, &arangodb.CollectionDocumentCreateOptions{})
readerCrt, err := col.CreateDocuments(ctx, []any{doc1, doc2})
require.NoError(t, err)
require.NotEmpty(t, meta.Rev)
require.Empty(t, meta.Old)
require.Empty(t, meta.New)

rdoc, err := col.ReadDocument(ctx, "test", &doc)
require.NoError(t, err)
metaCrt, errs := readerCrt.ReadAll()

require.EqualValues(t, "test", rdoc.Key)
})
})
})
require.ElementsMatch(t, []any{doc1.Key, doc2.Key}, []any{metaCrt[0].Key, metaCrt[1].Key})
require.ElementsMatch(t, []any{nil, nil}, errs)

WithDatabase(t, client, nil, func(db arangodb.Database) {
WithCollectionV2(t, db, nil, func(col arangodb.Collection) {
withContextT(t, defaultTestTimeout, func(ctx context.Context, tb testing.TB) {
doc := DocWithCode{
Key: "test",
}
doc2 := DocWithCode{
Key: "test2",
}
var docRedRead []DocWithCode

_, err := col.CreateDocuments(ctx, []any{
doc, doc2,
readeRed, err := col.ReadDocuments(ctx, []string{
"test", "test2", "nonexistent",
})
require.NoError(t, err)

docs, err := col.ReadDocuments(ctx, []string{
"test",
"tz44",
"test2",
})
require.NoError(t, err)
metaRed, errs := readeRed.ReadAll(&docRedRead)

require.ElementsMatch(t, []any{doc1.Key, doc2.Key}, []any{metaRed[0].Key, metaRed[1].Key})
require.ElementsMatch(t, []any{nil, nil, shared.ErrArangoDocumentNotFound}, []any{errs[0], errs[1], errs[2].(shared.ArangoError).ErrorNum})

var z DocWithCode
var docOldObject DocWithCode
var docDelRead []DocWithCode

meta, err := docs.Read(&z)
readerDel, err := col.DeleteDocumentsWithOptions(ctx, []string{
"test", "test2", "nonexistent",
}, &arangodb.CollectionDocumentDeleteOptions{OldObject: &docOldObject})
require.NoError(t, err)
require.EqualValues(t, "test", meta.Key)

_, err = docs.Read(&z)
require.Error(t, err)
require.True(t, shared.IsNotFound(err))
metaDel, errs := readerDel.ReadAll(&docDelRead)

meta, err = docs.Read(&z)
require.NoError(t, err)
require.EqualValues(t, "test2", meta.Key)
require.ElementsMatch(t, []any{doc1.Key, doc2.Key, ""}, []any{metaDel[0].Key, metaDel[1].Key, metaDel[2].Key})
require.ElementsMatch(t, []any{nil, nil, shared.ErrArangoDocumentNotFound}, []any{errs[0], errs[1], errs[2].(shared.ArangoError).ErrorNum})

// Will fail as the OldObject is not supported by the ReadAll
require.ElementsMatch(t, []any{doc1.Code, doc2.Code}, []any{metaDel[0].Old.(*DocWithCode).Code, metaDel[1].Old.(*DocWithCode).Code})

_, err = docs.Read(&z)
require.Error(t, err)
require.True(t, shared.IsNoMoreDocuments(err))
})
})
})
Expand Down