From 6bf10ff3e3b6fdaf67f50eeb60d343af4b0869a8 Mon Sep 17 00:00:00 2001 From: Jan Christoph Uhde Date: Tue, 12 Nov 2019 10:57:00 +0100 Subject: [PATCH] DEVSUP-492 (#10379) --- CHANGELOG | 14 +++++++++++++ arangod/Aql/Ast.cpp | 5 ++--- tests/js/server/aql/aql-modify.js | 33 +++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 5fc9ac6bff45..1cb87c40478d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,20 @@ v3.5.3 (XXXX-XX-XX) ------------------- +* Fixed UPSERT matching. + + Empty objects in the `UPSERT { ... }` expression will not be omitted anymore: + + db._collection("col").insert({ "find" : "me" }); + db._query(` UPSERT { "find" : "me", "foo" : {} } + UPDATE { "foo" : "not gonna happen" } + INSERT { "find" : "me", "foo" : {} } + INTO col + `) + + This will now correctly insert a document instead of updating the existing, + that only partially machtes the upsert-expression. + * Stop putting system services in _apps on single server, this has never worked on cluster and was not needed. diff --git a/arangod/Aql/Ast.cpp b/arangod/Aql/Ast.cpp index 57a643ddc49b..ec7726d02d68 100644 --- a/arangod/Aql/Ast.cpp +++ b/arangod/Aql/Ast.cpp @@ -2665,7 +2665,6 @@ AstNode* Ast::makeConditionFromExample(AstNode const* node) { TRI_ASSERT(object->type == NODE_TYPE_OBJECT); auto const n = object->numMembers(); - for (size_t i = 0; i < n; ++i) { auto member = object->getMember(i); @@ -2680,8 +2679,8 @@ AstNode* Ast::makeConditionFromExample(AstNode const* node) { auto value = member->getMember(0); - if (value->type == NODE_TYPE_OBJECT) { - createCondition(value); + if (value->type == NODE_TYPE_OBJECT && value->numMembers() != 0) { + createCondition(value); } else { auto access = variable; for (auto const& it : attributeParts) { diff --git a/tests/js/server/aql/aql-modify.js b/tests/js/server/aql/aql-modify.js index 72810dbc4be5..c7b180126ffe 100644 --- a/tests/js/server/aql/aql-modify.js +++ b/tests/js/server/aql/aql-modify.js @@ -1127,6 +1127,39 @@ function aqlUpsertOptionsSuite() { validateDocsAreUpdated(docs, invalid, true); }, + testUpsertEmptyObject: function () { + let NEW, OLD, res; + col.insert({ "value1": "find me" }); + + // before "find me" was found because the empty object + // was ignored now we will insert instead + let q1 = `UPSERT { "value1" : "find me", "value2" : {} } + INSERT { "value1" : "find me", "value2" : {} } + UPDATE { "value1" : "not gonna happen" } + IN ${collectionName} + RETURN [$OLD, $NEW]`; + + res = db._query(q1).toArray(); + OLD = res[0][0]; + NEW = res[0][1]; + assertEqual(NEW.value1, "find me"); + assertEqual(NEW.value2, {}); + + + // now we update the exact doucment + let q2 = `UPSERT { "value1" : "find me", "value2" : {} } + INSERT { "value1" : "not gonna happen" } + UPDATE { "value1" : "update" } + IN ${collectionName} + RETURN [$OLD, $NEW]`; + + res = db._query(q2).toArray(); + OLD = res[0][0]; + NEW = res[0][1]; + assertEqual(NEW.value1, "update"); + assertEqual(NEW.value2, {}); + }, + /* We cannot yet solve this. If you need to ensure _rev value checks put them in the UPDATE {} clause testUpsertSingleWithInvalidRevInMatch : function () { const invalid = genInvalidValue();