//////////////////////////////////////////////////////////////////////////////// /// DISCLAIMER /// /// Copyright 2019 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 /// /// @author Markus Pfeiffer //////////////////////////////////////////////////////////////////////////////// #include "SimpleModifier.h" #include "Aql/AqlValue.h" #include "Aql/Collection.h" #include "Aql/ModificationExecutor.h" #include "Aql/ModificationExecutorHelpers.h" #include "Aql/OutputAqlItemRow.h" #include "Basics/Common.h" #include "Basics/VelocyPackHelper.h" #include "VocBase/LogicalCollection.h" #include #include using namespace arangodb; using namespace arangodb::aql; using namespace arangodb::aql::ModificationExecutorHelpers; using namespace arangodb::basics; template SimpleModifier::OutputIterator::OutputIterator( SimpleModifier const& modifier) : _modifier(modifier), _operationsIterator(modifier._operations.begin()), _resultsIterator(modifier.getResultsIterator()) {} template typename SimpleModifier::OutputIterator& SimpleModifier::OutputIterator::next() { // Only move results on if there has been a document // submitted to the transaction if (_operationsIterator->first == ModifierOperationType::ReturnIfAvailable) { ++_resultsIterator; } ++_operationsIterator; return *this; } template typename SimpleModifier::OutputIterator& SimpleModifier::OutputIterator::operator++() { return next(); } template bool SimpleModifier::OutputIterator::operator!=( SimpleModifier::OutputIterator const& other) const noexcept { return _operationsIterator != other._operationsIterator; } template ModifierOutput SimpleModifier::OutputIterator::operator*() const { switch (_operationsIterator->first) { case ModifierOperationType::ReturnIfAvailable: { // This means the results slice is relevant if (_modifier.resultAvailable()) { VPackSlice elm = *_resultsIterator; bool error = VelocyPackHelper::getBooleanValue(elm, StaticStrings::Error, false); if (error) { return ModifierOutput{_operationsIterator->second, ModifierOutput::Type::SkipRow}; } else { return ModifierOutput{ _operationsIterator->second, ModifierOutput::Type::ReturnIfRequired, ModificationExecutorHelpers::getDocumentOrNull(elm, StaticStrings::Old), ModificationExecutorHelpers::getDocumentOrNull(elm, StaticStrings::New)}; } } else { return ModifierOutput{_operationsIterator->second, ModifierOutput::Type::CopyRow}; } case ModifierOperationType::CopyRow: return ModifierOutput{_operationsIterator->second, ModifierOutput::Type::CopyRow}; case ModifierOperationType::SkipRow: return ModifierOutput{_operationsIterator->second, ModifierOutput::Type::SkipRow}; } } // Shut up compiler TRI_ASSERT(false); return ModifierOutput{_operationsIterator->second, ModifierOutput::Type::SkipRow}; } template typename SimpleModifier::OutputIterator SimpleModifier::OutputIterator::begin() const { return SimpleModifier::OutputIterator(this->_modifier); } template typename SimpleModifier::OutputIterator SimpleModifier::OutputIterator::end() const { auto it = SimpleModifier::OutputIterator(this->_modifier); it._operationsIterator = _modifier._operations.end(); return it; } template void SimpleModifier::reset() { _accumulator = std::make_unique(); _operations.clear(); _results = OperationResult{}; } template Result SimpleModifier::accumulate(InputAqlItemRow& row) { TRI_ASSERT(_accumulator != nullptr); auto result = _completion.accumulate(*_accumulator.get(), row); _operations.push_back({result, row}); return Result{}; } template void SimpleModifier::transact() { _results = _completion.transact(_accumulator->closeAndGetContents()); throwOperationResultException(_infos, _results); } template size_t SimpleModifier::nrOfOperations() const { return _operations.size(); } template size_t SimpleModifier::nrOfDocuments() const { return _accumulator->nrOfDocuments(); } template size_t SimpleModifier::nrOfResults() const { if (_results.hasSlice() && _results.slice().isArray()) { return _results.slice().length(); } return 0; } template size_t SimpleModifier::nrOfErrors() const { size_t nrOfErrors{0}; for (auto const& pair : _results.countErrorCodes) { nrOfErrors += pair.second; } return nrOfErrors; } template size_t SimpleModifier::nrOfWritesExecuted() const { return nrOfDocuments() - nrOfErrors(); } template size_t SimpleModifier::nrOfWritesIgnored() const { return nrOfErrors(); } template ModificationExecutorInfos& SimpleModifier::getInfos() const noexcept { return _infos; } template size_t SimpleModifier::getBatchSize() const noexcept { return _batchSize; } template bool SimpleModifier::resultAvailable() const { return (nrOfDocuments() > 0 && !_infos._options.silent); } template VPackArrayIterator SimpleModifier::getResultsIterator() const { if (resultAvailable()) { TRI_ASSERT(_results.hasSlice() && _results.slice().isArray()); return VPackArrayIterator{_results.slice()}; } return VPackArrayIterator{VPackSlice::emptyArraySlice()}; } template class ::arangodb::aql::SimpleModifier; template class ::arangodb::aql::SimpleModifier; template class ::arangodb::aql::SimpleModifier;