1
0
Fork 0
arangodb/arangod/Aql/ModificationExecutor.h

166 lines
6.2 KiB
C++

////////////////////////////////////////////////////////////////////////////////
/// 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
////////////////////////////////////////////////////////////////////////////////
#ifndef ARANGOD_AQL_MODIFICATION_EXECUTOR_H
#define ARANGOD_AQL_MODIFICATION_EXECUTOR_H
#include "Aql/ExecutionState.h"
#include "Aql/InputAqlItemRow.h"
#include "Aql/ModificationExecutorInfos.h"
#include "Aql/OutputAqlItemRow.h"
#include "Aql/Stats.h"
#include "Utils/OperationResult.h"
#include <velocypack/Builder.h>
#include <velocypack/Iterator.h>
#include <velocypack/Slice.h>
#include <velocypack/velocypack-aliases.h>
namespace arangodb {
namespace aql {
//
// ModificationExecutor is the "base" class for the Insert, Remove,
// UpdateReplace and Upsert executors.
//
// The fetcher and modification-specific code is spliced in via a template for
// performance reasons
//
// A ModifierType has to provide the function accumulate, which batches updates
// to be submitted to the transaction, a function transact which submits the
// currently accumulated batch of updates to the transaction, and an iterator to
// retrieve the results of the transaction.
//
// There currently are 4 modifier types: Insert, Remove, UpdateReplace, and
// Upsert. These are divided into three *simple* modifiers, Insert, Remove,
// UpdateReplace, and the special Upsert modifier.
//
// The Upsert modifier is a mix of Insert and UpdateReplace, and hence more
// complicated. In the future it should share as much code as possible with the
// Insert and UpdateReplace modifiers. This might enable the removal of the
// extra SimpleModifier layer described below.
//
// The simple modifiers are created by instantiating the SimpleModifier template
// class (defined in SimpleModifier.h) with a *completion*.
// The for completions for SimpleModifiers are defined in InsertModifier.h,
// RemoveModifier.h, and UpdateReplaceModifier.h
//
// The FetcherType has to provide the function fetchRow with the parameter atMost
//
// The two types of modifiers (Simple and Upsert) follow a similar design. The main
// data is held in
// * an operations vector which stores the type of operation
// (APPLY_RETURN, IGNORE_RETURN, IGNORE_SKIP) that was performed by the
// modifier. The Upsert modifier internally uses APPLY_UPDATE and APPLY_INSERT
// to distinguish between the insert and UpdateReplace branches.
// * an accumulator that stores the documents that are committed in the
// transaction.
//
enum class ModOperationType : uint8_t {
// do not apply, do not produce a result - used for skipping over suppressed
// errors
IGNORE_SKIP = 0,
// do not apply, but pass the row to the next block - used for smart graphs
// and such
IGNORE_RETURN = 1,
// apply it and return the result
APPLY_RETURN = 2,
// TODO: These next two should be moved into the upsert modifier, as they
// are internal to it
// apply it and return the result, used only used *internally* in the UPSERT
// modifier
APPLY_UPDATE = 3,
// apply it and return the result, used only used *internally* in the UPSERT
// modifier
APPLY_INSERT = 4,
};
// The tuple ModifierOutput is what is returned by the result iterator of a
// modifier, and represents the results of the modification operation on the
// input row.
// The first component has to be the operation type, the second an
// InputAqlItemRow, and the third is a VPackSlice containing the result of the
// transaction for this row.
// using ModifierOutput = std::tuple<ModOperationType, InputAqlItemRow, VPackSlice>;
class ModifierOutput {
public:
ModifierOutput() = delete;
ModifierOutput(InputAqlItemRow const inputRow, bool const error);
ModifierOutput(InputAqlItemRow const inputRow, bool const error,
std::unique_ptr<AqlValue>&& oldValue, std::unique_ptr<AqlValue>&& newValue);
ModifierOutput(ModifierOutput&& o);
ModifierOutput& operator=(ModifierOutput&& o);
InputAqlItemRow getInputRow() const;
bool isError() const;
bool hasOldValue() const;
AqlValue&& getOldValue() const;
bool hasNewValue() const;
AqlValue&& getNewValue() const;
private:
// No copying or copy assignment allowed of this class or any derived class
ModifierOutput(ModifierOutput const&);
ModifierOutput& operator=(ModifierOutput const&);
InputAqlItemRow const _inputRow;
bool const _error;
std::unique_ptr<AqlValue> _oldValue;
std::unique_ptr<AqlValue> _newValue;
};
template <typename FetcherType, typename ModifierType>
class ModificationExecutor {
public:
struct Properties {
static constexpr bool preservesOrder = true;
static constexpr BlockPassthrough allowsBlockPassthrough = BlockPassthrough::Disable;
static constexpr bool inputSizeRestrictsOutputSize = false;
};
using Fetcher = FetcherType;
using Infos = ModificationExecutorInfos;
using Stats = ModificationStats;
ModificationExecutor(FetcherType&, Infos&);
~ModificationExecutor();
std::pair<ExecutionState, Stats> produceRows(OutputAqlItemRow& output);
protected:
std::pair<ExecutionState, Stats> doCollect(size_t const maxOutputs);
void doOutput(OutputAqlItemRow& output, Stats& stats);
// The state that was returned on the last call to produceRows. For us
// this is relevant because we might have collected some documents in the
// modifier's accumulator, but not written them yet, because we ran into
// WAITING
ExecutionState _lastState;
ModificationExecutorInfos& _infos;
FetcherType& _fetcher;
ModifierType _modifier;
};
} // namespace aql
} // namespace arangodb
#endif