From 5367dec865a244db833194f6cecbc9a69bb3f975 Mon Sep 17 00:00:00 2001 From: Michael Hackstein Date: Tue, 3 May 2016 13:48:28 +0200 Subject: [PATCH 1/2] If there is an error in Modification Blocks the request for this document is now correctly skipped on single-doc case. --- arangod/Aql/ModificationBlocks.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arangod/Aql/ModificationBlocks.cpp b/arangod/Aql/ModificationBlocks.cpp index 3fa2cb81bf..688b3ddb81 100644 --- a/arangod/Aql/ModificationBlocks.cpp +++ b/arangod/Aql/ModificationBlocks.cpp @@ -588,6 +588,10 @@ AqlItemBlock* UpdateBlock::work(std::vector& blocks) { VPackSlice toUpdate = object.slice(); + if (toUpdate.isNone()) { + continue; + } + // fetch old revision OperationResult opRes = _trx->update(_collection->name, toUpdate, options); if (!isMultiple) { @@ -983,6 +987,10 @@ AqlItemBlock* ReplaceBlock::work(std::vector& blocks) { } VPackSlice toUpdate = object.slice(); + + if (toUpdate.isNone()) { + continue; + } // fetch old revision OperationResult opRes = _trx->replace(_collection->name, toUpdate, options); if (!isMultiple) { From d79f4d1d10827ba565e36834be5607e99a0da9ec Mon Sep 17 00:00:00 2001 From: Michael Hackstein Date: Tue, 3 May 2016 14:23:42 +0200 Subject: [PATCH 2/2] UPSERT Block now forbids storing a key if the collection is not sharded by it. --- arangod/Aql/ModificationBlocks.cpp | 18 ++++++++++++++++-- arangod/Aql/ModificationBlocks.h | 3 +++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/arangod/Aql/ModificationBlocks.cpp b/arangod/Aql/ModificationBlocks.cpp index 688b3ddb81..a44bdbd40e 100644 --- a/arangod/Aql/ModificationBlocks.cpp +++ b/arangod/Aql/ModificationBlocks.cpp @@ -653,6 +653,16 @@ AqlItemBlock* UpdateBlock::work(std::vector& blocks) { UpsertBlock::UpsertBlock(ExecutionEngine* engine, UpsertNode const* ep) : ModificationBlock(engine, ep) {} +bool UpsertBlock::isShardKeyError(VPackSlice const slice) const { + TRI_ASSERT(_isDBServer); + + if (_usesDefaultSharding) { + return false; + } + + return slice.hasKey(StaticStrings::KeyString); +} + /// @brief the actual work horse for inserting data AqlItemBlock* UpsertBlock::work(std::vector& blocks) { size_t const count = countBlocksRows(blocks); @@ -762,8 +772,12 @@ AqlItemBlock* UpsertBlock::work(std::vector& blocks) { AqlValue const& insertDoc = res->getValueReference(i, insertRegisterId); VPackSlice toInsert = insertDoc.slice(); if (toInsert.isObject()) { - insertBuilder.add(toInsert); - insRows.emplace_back(dstRow); + if (_isDBServer && isShardKeyError(toInsert)) { + errorCode = TRI_ERROR_CLUSTER_MUST_NOT_SPECIFY_KEY; + } else { + insertBuilder.add(toInsert); + insRows.emplace_back(dstRow); + } } else { errorCode = TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID; } diff --git a/arangod/Aql/ModificationBlocks.h b/arangod/Aql/ModificationBlocks.h index 3e50259096..ceb6fb719f 100644 --- a/arangod/Aql/ModificationBlocks.h +++ b/arangod/Aql/ModificationBlocks.h @@ -126,6 +126,9 @@ class UpsertBlock : public ModificationBlock { protected: /// @brief the actual work horse for updating data AqlItemBlock* work(std::vector&) override final; + + private: + bool isShardKeyError(arangodb::velocypack::Slice const) const; }; } // namespace arangodb::aql