diff --git a/v2/arangodb/collection_documents_create.go b/v2/arangodb/collection_documents_create.go index 846c99d9..53d4c914 100644 --- a/v2/arangodb/collection_documents_create.go +++ b/v2/arangodb/collection_documents_create.go @@ -49,20 +49,22 @@ type CollectionDocumentCreate interface { // CreateDocuments creates multiple documents in the collection. // The document data is loaded from the given documents slice, the documents metadata is returned. - // If a documents element already contains a `_key` field, this will be used as key of the new document, + // If a document element already contains a `_key` field, this will be used as key of the new document, // otherwise a unique key is created. - // If a documents element contains a `_key` field with a duplicate key, other any other field violates an index constraint, - // a ConflictError is returned in its indeed in the errors slice. + // If a document element contains a `_key` field with a duplicate key, or any other field that violates an index constraint, + // then the ConflictError for a specific document will be returned only while reading from CollectionDocumentCreateResponseReader + // and not as the error output of this function. // If the create request itself fails or one of the arguments is invalid, an error is returned. // SmartGraphs and EnterpriseGraphs cannot use existing collections and cannot use the document interface CreateDocuments(ctx context.Context, documents interface{}) (CollectionDocumentCreateResponseReader, error) // CreateDocumentsWithOptions creates multiple documents in the collection. // The document data is loaded from the given documents slice, the documents metadata is returned. - // If a documents element already contains a `_key` field, this will be used as key of the new document, + // If a document element already contains a `_key` field, this will be used as key of the new document, // otherwise a unique key is created. - // If a documents element contains a `_key` field with a duplicate key, other any other field violates an index constraint, - // a ConflictError is returned in its indeed in the errors slice. + // If a document element contains a `_key` field with a duplicate key, or any other field that violates an index constraint, + // then the ConflictError for a specific document will be returned only while reading from CollectionDocumentCreateResponseReader + // and not as the error output of this function. // If the create request itself fails or one of the arguments is invalid, an error is returned. // SmartGraphs and EnterpriseGraphs cannot use existing collections and cannot use the document interface CreateDocumentsWithOptions(ctx context.Context, documents interface{}, opts *CollectionDocumentCreateOptions) (CollectionDocumentCreateResponseReader, error) diff --git a/v2/arangodb/shared/error.go b/v2/arangodb/shared/error.go index f2aa97bf..b6477221 100644 --- a/v2/arangodb/shared/error.go +++ b/v2/arangodb/shared/error.go @@ -1,7 +1,7 @@ // // DISCLAIMER // -// Copyright 2017-2024 ArangoDB GmbH, Cologne, Germany +// 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. @@ -26,6 +26,7 @@ import ( "fmt" "io" "net/http" + "regexp" ) const ( @@ -423,6 +424,23 @@ func (ae ArangoError) Temporary() bool { return ae.HasError && ae.Code == http.StatusServiceUnavailable } +// GetConflictKey if error was caused by Conflict it returns the key that caused it or "" otherwise +func (ae ArangoError) GetConflictKey() string { + if IsConflict(error(ae)) { + // Whitespace symbols are not allowed as part of a key so trimming them will not result in a mistake. + re := regexp.MustCompile(`conflicting key:\s*(.+)$`) + match := re.FindStringSubmatch(ae.ErrorMessage) + if len(match) == 1 { + return match[1] + } else { + return "" + } + + } else { + return "" + } +} + // newArangoError creates a new ArangoError with given values. func newArangoError(code, errorNum int, errorMessage string) error { return ArangoError{ diff --git a/v2/arangodb/shared/response.go b/v2/arangodb/shared/response.go index 00d77a59..249acb87 100644 --- a/v2/arangodb/shared/response.go +++ b/v2/arangodb/shared/response.go @@ -100,6 +100,10 @@ func (r ResponseStruct) AsArangoError() ArangoError { a.ErrorMessage = *r.ErrorMessage } + if r.ErrorMessage != nil { + a.ErrorMessage = *r.ErrorMessage + } + return a } diff --git a/v2/tests/database_collection_doc_create_test.go b/v2/tests/database_collection_doc_create_test.go index 2c1d1a5f..9eaa181e 100644 --- a/v2/tests/database_collection_doc_create_test.go +++ b/v2/tests/database_collection_doc_create_test.go @@ -1,7 +1,7 @@ // // DISCLAIMER // -// Copyright 2023-2024 ArangoDB GmbH, Cologne, Germany +// Copyright 2023-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. @@ -24,6 +24,7 @@ import ( "context" "testing" + "github.com/arangodb/go-driver/v2/arangodb/shared" "github.com/arangodb/go-driver/v2/utils" "github.com/stretchr/testify/require" @@ -77,6 +78,8 @@ func Test_DatabaseCollectionDocCreateOverwrite(t *testing.T) { OverwriteMode: overwriteMode.New(), }) require.Error(t, err) + + require.Equal(t, meta.Key, err.(shared.ArangoError).GetConflictKey()) require.Empty(t, metaConflict.Rev) require.Empty(t, metaConflict.Old) require.Empty(t, metaConflict.New)