/**
 *   Copyright 2011-2015 Quickstep Technologies LLC.
 *   Copyright 2015 Pivotal Software, Inc.
 *
 *   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.
 **/

#ifndef QUICKSTEP_STORAGE_VALUE_ACCESSOR_HPP_
#define QUICKSTEP_STORAGE_VALUE_ACCESSOR_HPP_

#include <algorithm>
#include <cstdint>
#include <limits>
#include <memory>
#include <type_traits>
#include <utility>
#include <vector>

#include "catalog/CatalogAttribute.hpp"
#include "catalog/CatalogRelationSchema.hpp"
#include "catalog/CatalogTypedefs.hpp"
#include "storage/StorageBlockInfo.hpp"
#include "storage/TupleIdSequence.hpp"
#include "types/TypedValue.hpp"
#include "types/containers/Tuple.hpp"
#include "utility/Macros.hpp"

namespace quickstep {

class TupleStorageSubBlock;

// TODO(chasseur): Iteration on ValueAccessors is row-at-a-time, but in some
// cases column-wise data movement may be more efficient.

/** \addtogroup Storage
 *  @{
 */

/**
 * @brief Base class for accessors which provide inline-able methods allowing
 *        direct access to attribute values in TupleStorageSubBlocks or
 *        ColumnVectors.
 * @note This base class provides several virtual methods named with the suffix
 *       -Virtual that constitute a common interface that all ValueAccessors
 *       support. Concrete implementation subclasses of ValueAccessor all
 *       provide non-virtual inline versions of these methods without the
 *       -Virtual suffix. The general recommendation is that if client code
 *       only needs to make one or two calls to methods of a ValueAccessor, it
 *       can just use the virtual methods and avoid generating many code
 *       branches for different types of ValueAccessors. If, on the other hand,
 *       methods of a ValueAccessor will be called many times repeatedly (e.g.
 *       in an inner loop), it is recommended to downcast a ValueAccessor to
 *       its concrete type and use the inline methods. The file
 *       ValueAccessorUtil.hpp provides macros to do this automatically.
 **/
class ValueAccessor {
 public:
  /**
   * @brief Enum with cases for different subclasses of ValueAccessor.
   **/
  enum class Implementation {
    // Accessors for values inside a TupleStorageSubBlock:
    kBasicColumnStore,
    kCompressedColumnStore,
    kCompressedPackedRowStore,
    kPackedRowStore,
    kSplitRowStore,
    // Accessor for a group of ColumnVectors:
    kColumnVectors
  };

  ValueAccessor() {
  }

  virtual ~ValueAccessor() {
  }

  /**
   * @brief Determine the concrete type of this ValueAccessor.
   * @note See also isTupleIdSequenceAdapter() and
   *       isOrderedTupleIdSequenceAdapter(), which check if a templated
   *       adapter is being used.
   *
   * @return The implementation type of this ValueAccessor.
   **/
  virtual Implementation getImplementationType() const = 0;

  /**
   * @brief Determine if this ValueAccessor is a
   *        TupleIdSequenceAdapterValueAccessor.
   *
   * @return true if this is a TupleIdSequenceAdapterValueAccessor, false
   *         otherwise.
   **/
  virtual bool isTupleIdSequenceAdapter() const = 0;

  /**
   * @brief Determine if this ValueAccessor is an
   *        OrderedTupleIdSequenceAdapterValueAccessor.
   *
   * @return true if thhis is an OrderedTupleIdSequenceAdapterValueAccessor,
   *         false otherwise.
   **/
  virtual bool isOrderedTupleIdSequenceAdapter() const = 0;

  /**
   * @brief Start statefully iterating over tuples from this ValueAccessor.
   * @note Conceptually, this method sets the "position" of the ValueAccessor
   *       to one-before the start of tuples. nextVirtual()/next() should be
   *       called before attempting to read values.
   **/
  virtual void beginIterationVirtual() = 0;

  /**
   * @brief Determine whether the stateful iteration over tuples in this
   *        ValueAccessor is finished (i.e. there are no more tuples to iterate
   *        over).
   *
   * @return true if iteration is finished (i.e. a subsequent call to
   *         nextVirtual()/next() will return false). Note that this returns
   *         true if iteration is past-the-end of tuples OR on the very last
   *         tuple.
   **/
  virtual bool iterationFinishedVirtual() const = 0;

  /**
   * @brief Advance stateful iteration to the next tuple from this
   *        ValueAccessor.
   *
   * @return true if advanced to another tuple, false if there are no more
   *         tuples.
   **/
  virtual bool nextVirtual() = 0;

  /**
   * @brief Rewind stateful iteration by one tuple (i.e. undo the last call to
   *        nextVirtual()/next()).
   **/
  virtual void previousVirtual() = 0;

  /**
   * @brief Get the current absolute position of stateful iteration on this
   *        ValueAccessor (i.e. the tuple_id of the corresponding tuple in a
   *        TupleStorageSubBlock).
   *
   * @return The absolute position of the current tuple in stateful iteration.
   **/
  virtual tuple_id getCurrentPositionVirtual() const = 0;

  /**
   * @brief Get the "end" absolute position of tuples accessible via this
   *        ValueAccessor (i.e. the absolute position of the last tuple plus
   *        one).
   *
   * @return The end position of tuples accessible via this ValueAccessor.
   **/
  virtual tuple_id getEndPositionVirtual() const = 0;

  /**
   * @brief Get the actual number of tuples accessible via this ValueAccessor.
   * @note This is different from getEndPositionVirtual()/getEndPosition(),
   *       because there may be gaps in the sequence of tuple positions that a
   *       ValueAccessor iterates over (e.g. because a
   *       TupleIdSequenceAdapterValueAccessor is being used, or because the
   *       base TupleStorageSubBlock (e.g. SplitRowStoreTupleStorageSubBlock)
   *       allows empty tuple slots).
   *
   * @return The actual number of tuples accessible via this ValueAccessor.
   **/
  virtual tuple_id getNumTuplesVirtual() const = 0;

  /**
   * @brief Get a pointer to an untyped value for the current tuple in stateful
   *        iteration.
   * @note The inline version of this method provided by subclasses,
   *       getUntypedValue(), takes an optional bool template parameter
   *       indicating whether checks for null-values should be performed. If it
   *       is known that the Type for an attribute is not nullable, using false
   *       for that template parameter may result in a faster version of the
   *       method that avoids a branch to check for nulls.
   * @warning This method should only be called if the previous call to
   *          nextVirtual()/next() return true.
   *
   * @param attr_id The attribute_id indicating which attribute's value to get
   *        from the current tuple.
   * @return An untyped pointer to the attribute value specified by attr_id for
   *         the current tuple.
   **/
  virtual const void* getUntypedValueVirtual(const attribute_id attr_id) const = 0;

  /**
   * @brief Get a TypedValue for the current tuple in stateful iteration.
   * @warning This method should only be called if the previous call to
   *          nextVirtual()/next() return true.
   *
   * @param attr_id The attribute_id indicating which attribute's value to get
   *        from the current tuple.
   * @return The attribute value specified by attr_id for the current tuple.
   **/
  virtual TypedValue getTypedValueVirtual(const attribute_id attr_id) const = 0;

  /**
   * @brief Get a pointer to an untyped value for the tuple at an explicitly
   *        specified absolute position.
   * @note The inline version of this method provided by subclasses,
   *       getUntypedValueAtAbsolutePosition(), takes an optional bool template
   *       parameter indicating whether checks for null-values should be
   *       performed. If it is known that the Type for an attribute is not
   *       nullable, using false for that template parameter may result in a
   *       faster version of the method that avoids a branch to check for
   *       nulls.
   * @warning It is the caller's responsbility to ensure that there actually is
   *          a tuple at the specified position.
   *
   * @param attr_id The attribute_id indicating which attribute's value to get.
   * @param tid The absolute position of the tuple to get a value from.
   * @return An untyped pointer to the attribute value specified by attr_id in
   *         the tuple at the position specified by tid.
   **/
  virtual const void* getUntypedValueAtAbsolutePositionVirtual(
      const attribute_id attr_id,
      const tuple_id tid) const = 0;

  /**
   * @brief Get a TypedValue for the tuple at an explicitly specified absolute
   *        position.
   * @warning It is the caller's responsbility to ensure that there actually is
   *          a tuple at the specified position.
   *
   * @param attr_id The attribute_id indicating which attribute's value to get.
   * @param tid The absolute position of the tuple to get a value from.
   * @return The attribute value specified by attr_id in the tuple at the
   *         position specified by tid.
   **/
  virtual TypedValue getTypedValueAtAbsolutePositionVirtual(
      const attribute_id attr_id,
      const tuple_id tid) const = 0;

  /**
   * @brief Create a Tuple object containing all the attribute values for the
   *        current tuple in stateful iteration.
   * @warning This method should only be called if the previous call to
   *          nextVirtual()/next() return true.
   *
   * @return A new Tuple object (caller takes ownership) containing all the
   *         attribute values for the current tuple in stateful iteration.
   **/
  virtual Tuple* getTupleVirtual() const = 0;

  /**
   * @brief Create a Tuple object containing values of explicitly-specified
   *        attributes in a specified order for the current tuple in stateful
   *        iteration.
   * @warning This method should only be called if the previous call to
   *          nextVirtual()/next() return true.
   *
   * @param attributes The IDs of attributes, in the desired order, to fill
   *        the returned Tuple with.
   * @return A new Tuple object (caller takes ownership) containing the
   *         specified attribute values for the current tuple in stateful
   *         iteration.
   **/
  virtual Tuple* getTupleWithAttributesVirtual(
      const std::vector<attribute_id> &attributes) const = 0;

  /**
   * @brief Create a new TupleIdSequenceAdapterValueAccessor that wraps this
   *        ValueAccessor.
   * @warning The newly-created adapter does NOT take ownership of this
   *          ValueAccessor nor the provided TupleIdSequence. Both must remain
   *          valid so long as the adapter will be used.
   *
   * @param id_sequence A TupleIdSequence specifying some subset of the tuples
   *        for this ValueAccessor that the adapter will iterate over.
   * @return A new TupleIdSequenceAdapterValueAccessor that will iterate over
   *         only the tuples specified in id_sequence.
   **/
  virtual ValueAccessor* createSharedTupleIdSequenceAdapterVirtual(
      const TupleIdSequence &id_sequence) = 0;

  /**
   * @brief Get a TupleIdSequence indicating which positions this ValueAccessor
   *        is iterating over.
   *
   * @return A pointer to a TupleIdSequence that indicates which absolute
   *         positions this ValueAccessor iterates over. Returns NULL if there
   *         are no gaps in the iteration sequence (i.e. iteration goes from
   *         position 0 to getEndPositionVirtual() - 1 without skipping
   *         anything).
   **/
  virtual const TupleIdSequence* getTupleIdSequenceVirtual() const = 0;

 private:
  DISALLOW_COPY_AND_ASSIGN(ValueAccessor);
};

template <typename InternalValueAccessorType>
class OrderedTupleIdSequenceAdapterValueAccessor;

/**
 * @brief Adapter for another ValueAccessor which only iterates over tuples in
 *        a TupleIdSequence.
 **/
template <typename InternalValueAccessorType>
class TupleIdSequenceAdapterValueAccessor : public ValueAccessor {
 public:
  TupleIdSequenceAdapterValueAccessor(InternalValueAccessorType *accessor,
                                      const TupleIdSequence &id_sequence,
                                      const bool take_ownership_of_accessor = true)
      : accessor_(accessor),
        owned_accessor_(take_ownership_of_accessor ? accessor : nullptr),
        id_sequence_(id_sequence),
        current_position_(id_sequence.before_begin()) {
  }

  ~TupleIdSequenceAdapterValueAccessor() override {
  }

  Implementation getImplementationType() const override {
    return accessor_->getImplementationType();
  }

  bool isTupleIdSequenceAdapter() const override {
    return true;
  }

  bool isOrderedTupleIdSequenceAdapter() const override {
    return false;
  }

  inline void beginIteration() {
    current_position_ = id_sequence_.before_begin();
  }

  inline bool iterationFinished() const {
    TupleIdSequence::const_iterator next_position = current_position_;
    ++next_position;
    return (current_position_ == id_sequence_.end())
           || (next_position == id_sequence_.end());
  }

  inline bool next() {
    ++current_position_;
    return current_position_ != id_sequence_.end();
  }

  inline void previous() {
    --current_position_;
  }

  inline tuple_id getCurrentPosition() const {
    return *current_position_;
  }

  inline tuple_id getEndPosition() const {
    return id_sequence_.length();
  }

  inline tuple_id getNumTuples() const {
    return id_sequence_.numTuples();
  }

  template <bool check_null = true>
  inline const void* getUntypedValue(const attribute_id attr_id) const {
    return accessor_->template getUntypedValueAtAbsolutePosition<check_null>(attr_id, *current_position_);
  }

  inline TypedValue getTypedValue(const attribute_id attr_id) const {
    return accessor_->getTypedValueAtAbsolutePosition(attr_id, *current_position_);
  }

  // Pass-through.
  template <bool check_null = true>
  inline const void* getUntypedValueAtAbsolutePosition(const attribute_id attr_id,
                                                       const tuple_id tid) const {
    return accessor_->template getUntypedValueAtAbsolutePosition<check_null>(attr_id, tid);
  }

  // Pass-through.
  inline TypedValue getTypedValueAtAbsolutePosition(const attribute_id attr_id,
                                                    const tuple_id tid) const {
    return accessor_->getTypedValueAtAbsolutePosition(attr_id, tid);
  }

  inline Tuple* getTuple() const {
    return accessor_->getTupleAtAbsolutePosition(*current_position_);
  }

  inline Tuple* getTupleWithAttributes(const std::vector<attribute_id> &attributes) const {
    return accessor_->getTupleAtAbsolutePositionWithAttributes(*current_position_, attributes);
  }

  inline TupleIdSequenceAdapterValueAccessor<InternalValueAccessorType> *createSharedTupleIdSequenceAdapter(
      const TupleIdSequence &id_sequence) {
    return new TupleIdSequenceAdapterValueAccessor<InternalValueAccessorType>(accessor_, id_sequence, false);
  }

  inline OrderedTupleIdSequenceAdapterValueAccessor<InternalValueAccessorType>
      *createSharedOrderedTupleIdSequenceAdapter(const OrderedTupleIdSequence &id_sequence) {
    return new OrderedTupleIdSequenceAdapterValueAccessor<InternalValueAccessorType>(accessor_, id_sequence, false);
  }

  inline const TupleIdSequence* getTupleIdSequence() const {
    return &id_sequence_;
  }

  // Implementation of virtuals that pass-through to the inline
  // implementations.
  void beginIterationVirtual() override {
    beginIteration();
  }

  bool iterationFinishedVirtual() const override {
    return iterationFinished();
  }

  bool nextVirtual() override {
    return next();
  }

  void previousVirtual() override {
    previous();
  }

  tuple_id getCurrentPositionVirtual() const override {
    return getCurrentPosition();
  }

  tuple_id getEndPositionVirtual() const override {
    return getEndPosition();
  }

  tuple_id getNumTuplesVirtual() const override {
    return getNumTuples();
  }

  const void* getUntypedValueVirtual(const attribute_id attr_id) const override {
    return getUntypedValue(attr_id);
  }

  TypedValue getTypedValueVirtual(const attribute_id attr_id) const override {
    return getTypedValue(attr_id);
  }

  const void* getUntypedValueAtAbsolutePositionVirtual(
      const attribute_id attr_id,
      const tuple_id tid) const override {
    return getUntypedValueAtAbsolutePosition(attr_id, tid);
  }

  TypedValue getTypedValueAtAbsolutePositionVirtual(
      const attribute_id attr_id,
      const tuple_id tid) const override {
    return getTypedValueAtAbsolutePosition(attr_id, tid);
  }

  Tuple* getTupleVirtual() const override {
    return getTuple();
  }

  Tuple* getTupleWithAttributesVirtual(
      const std::vector<attribute_id> &attributes) const override {
    return getTupleWithAttributes(attributes);
  }

  ValueAccessor* createSharedTupleIdSequenceAdapterVirtual(
      const TupleIdSequence &id_sequence) override {
    return createSharedTupleIdSequenceAdapter(id_sequence);
  }

  const TupleIdSequence* getTupleIdSequenceVirtual() const override {
    return getTupleIdSequence();
  }

 private:
  InternalValueAccessorType *accessor_;
  std::unique_ptr<InternalValueAccessorType> owned_accessor_;
  const TupleIdSequence &id_sequence_;
  TupleIdSequence::const_iterator current_position_;

  DISALLOW_COPY_AND_ASSIGN(TupleIdSequenceAdapterValueAccessor);
};

/**
 * @brief Adapter for another ValueAccessor which only iterates over tuples in
 *        an OrderedTupleIdSequence.
 **/
template <typename InternalValueAccessorType>
class OrderedTupleIdSequenceAdapterValueAccessor : public ValueAccessor {
 public:
  OrderedTupleIdSequenceAdapterValueAccessor(InternalValueAccessorType *accessor,
                                             const OrderedTupleIdSequence &id_sequence,
                                             const bool take_ownership_of_accessor = true)
      : accessor_(accessor),
        owned_accessor_(take_ownership_of_accessor ? accessor : nullptr),
        id_sequence_(id_sequence),
        current_position_(std::numeric_limits<OrderedTupleIdSequence::size_type>::max()) {
    static_assert(std::numeric_limits<OrderedTupleIdSequence::size_type>::is_modulo,
                  "size_type does not support modulo overflow.");
  }

  ~OrderedTupleIdSequenceAdapterValueAccessor() {
  }

  Implementation getImplementationType() const override {
    return accessor_->getImplementationType();
  }

  bool isTupleIdSequenceAdapter() const override {
    return false;
  }

  bool isOrderedTupleIdSequenceAdapter() const override {
    return true;
  }

  inline void beginIteration() {
    current_position_ = std::numeric_limits<OrderedTupleIdSequence::size_type>::max();
  }

  inline bool iterationFinished() const {
    return current_position_ + 1 >= id_sequence_.size();
  }

  inline bool next() {
    ++current_position_;
    return current_position_ != id_sequence_.size();
  }

  inline void previous() {
    --current_position_;
  }

  inline tuple_id getCurrentPosition() const {
    return id_sequence_[current_position_];
  }

  inline tuple_id getEndPosition() const {
    OrderedTupleIdSequence::const_iterator max_it = std::max_element(id_sequence_.begin(), id_sequence_.end());
    return (max_it != id_sequence_.end() ? *max_it : 0) + 1;
  }

  inline tuple_id getNumTuples() const {
    return id_sequence_.size();
  }

  template <bool check_null = true>
  inline const void* getUntypedValue(const attribute_id attr_id) const {
    return accessor_->template getUntypedValueAtAbsolutePosition<check_null>(attr_id,
                                                                             id_sequence_[current_position_]);
  }

  inline TypedValue getTypedValue(const attribute_id attr_id) const {
    return accessor_->getTypedValueAtAbsolutePosition(attr_id, id_sequence_[current_position_]);
  }

  template <bool check_null = true>
  inline const void* getUntypedValueAtAbsolutePosition(const attribute_id attr_id,
                                                       const tuple_id tid) const {
    FATAL_ERROR("getUntypedValueAtAbsolutePosition() not implemented in "
                "OrderedTupleIdSequenceAdapterValueAccessor");
  }

  inline TypedValue getTypedValueAtAbsolutePosition(const attribute_id attr_id,
                                                    const tuple_id tid) const {
    FATAL_ERROR("getTypedValueAtAbsolutePosition() not implemented in "
                "OrderedTupleIdSequenceAdapterValueAccessor");
  }

  inline Tuple* getTuple() const {
    return accessor_->getTupleAtAbsolutePosition(id_sequence_[current_position_]);
  }

  inline Tuple* getTupleWithAttributes(const std::vector<attribute_id> &attributes) const {
    return accessor_->getTupleAtAbsolutePositionWithAttributes(id_sequence_[current_position_], attributes);
  }

  inline TupleIdSequenceAdapterValueAccessor<InternalValueAccessorType>*
      createSharedTupleIdSequenceAdapter(const TupleIdSequence &id_sequence) {
    return new TupleIdSequenceAdapterValueAccessor<InternalValueAccessorType>(accessor_,
                                                                              id_sequence,
                                                                              false);
  }

  inline OrderedTupleIdSequenceAdapterValueAccessor<InternalValueAccessorType>
      *createSharedOrderedTupleIdSequenceAdapter(const OrderedTupleIdSequence &id_sequence) {
    return new OrderedTupleIdSequenceAdapterValueAccessor<InternalValueAccessorType>(accessor_, id_sequence, false);
  }

  inline const TupleIdSequence* getTupleIdSequence() const {
    FATAL_ERROR("getTupleIdSequence() not implemented in "
                "OrderedTupleIdSequenceAdapterValueAccessor");
  }

  // Implementation of virtuals that pass-through to the inline
  // implementations.
  void beginIterationVirtual() override {
    beginIteration();
  }

  bool iterationFinishedVirtual() const override {
    return iterationFinished();
  }

  bool nextVirtual() override {
    return next();
  }

  void previousVirtual() override {
    previous();
  }

  tuple_id getCurrentPositionVirtual() const override {
    return getCurrentPosition();
  }

  tuple_id getEndPositionVirtual() const override {
    return getEndPosition();
  }

  tuple_id getNumTuplesVirtual() const override {
    return getNumTuples();
  }

  const void* getUntypedValueVirtual(const attribute_id attr_id) const override {
    return getUntypedValue(attr_id);
  }

  TypedValue getTypedValueVirtual(const attribute_id attr_id) const override {
    return getTypedValue(attr_id);
  }

  const void* getUntypedValueAtAbsolutePositionVirtual(
      const attribute_id attr_id,
      const tuple_id tid) const override {
    return getUntypedValueAtAbsolutePosition(attr_id, tid);
  }

  TypedValue getTypedValueAtAbsolutePositionVirtual(
      const attribute_id attr_id,
      const tuple_id tid) const override {
    return getTypedValueAtAbsolutePosition(attr_id, tid);
  }

  Tuple* getTupleVirtual() const override {
    return getTuple();
  }

  Tuple* getTupleWithAttributesVirtual(
      const std::vector<attribute_id> &attributes) const override {
    return getTupleWithAttributes(attributes);
  }

  ValueAccessor* createSharedTupleIdSequenceAdapterVirtual(
      const TupleIdSequence &id_sequence) override {
    return createSharedTupleIdSequenceAdapter(id_sequence);
  }

  const TupleIdSequence* getTupleIdSequenceVirtual() const override {
    return getTupleIdSequence();
  }

 private:
  InternalValueAccessorType *accessor_;
  std::unique_ptr<InternalValueAccessorType> owned_accessor_;
  const OrderedTupleIdSequence &id_sequence_;
  OrderedTupleIdSequence::size_type current_position_;

  DISALLOW_COPY_AND_ASSIGN(OrderedTupleIdSequenceAdapterValueAccessor);
};

/**
 * @brief Templated implementation of ValueAccessor for any packed
 *        TupleStorageSubBlock.
 **/
template <typename TupleStorageSubBlockT,
          typename HelperT,
          ValueAccessor::Implementation impl_type>
class PackedTupleStorageSubBlockValueAccessor : public ValueAccessor {
 public:
  ~PackedTupleStorageSubBlockValueAccessor() override {
  }

  Implementation getImplementationType() const override {
    return impl_type;
  }

  bool isTupleIdSequenceAdapter() const override {
    return false;
  }

  bool isOrderedTupleIdSequenceAdapter() const override {
    return false;
  }

  inline void beginIteration() {
    current_tuple_ = -1;
  }

  inline bool iterationFinished() const {
    return current_tuple_ + 1 >= helper_.numPackedTuples();
  }

  inline bool next() {
    ++current_tuple_;
    return (current_tuple_ < helper_.numPackedTuples());
  }

  inline void previous() {
    --current_tuple_;
  }

  inline tuple_id getCurrentPosition() const {
    return current_tuple_;
  }

  inline tuple_id getEndPosition() const {
    return helper_.numPackedTuples();
  }

  inline tuple_id getNumTuples() const {
    return helper_.numPackedTuples();
  }

  template <bool check_null = true>
  inline const void* getUntypedValue(const attribute_id attr_id) const {
    return getUntypedValueAtAbsolutePosition<check_null>(attr_id, current_tuple_);
  }

  inline TypedValue getTypedValue(const attribute_id attr_id) const {
    return getTypedValueAtAbsolutePosition(attr_id, current_tuple_);
  }

  template <bool check_null = true>
  inline const void* getUntypedValueAtAbsolutePosition(const attribute_id attr_id,
                                                       const tuple_id tid) const {
    return helper_.template getAttributeValue<check_null>(tid, attr_id);
  }

  inline TypedValue getTypedValueAtAbsolutePosition(const attribute_id attr_id,
                                                    const tuple_id tid) const {
    return helper_.getAttributeValueTyped(tid, attr_id);
  }

  inline Tuple* getTuple() const {
    return getTupleAtAbsolutePosition(current_tuple_);
  }

  inline Tuple* getTupleWithAttributes(const std::vector<attribute_id> &attributes) const {
    return getTupleAtAbsolutePositionWithAttributes(current_tuple_, attributes);
  }

  inline Tuple* getTupleAtAbsolutePosition(const tuple_id tid) const {
    std::vector<TypedValue> values;
    if (relation_.gapsInAttributeSequence()) {
      for (const CatalogAttribute &attr : relation_) {
        values.emplace_back(getTypedValueAtAbsolutePosition(attr.getID(), tid));
      }
    } else {
      const attribute_id max_attr_id = relation_.getMaxAttributeId();
      for (attribute_id attr_id = 0;
           attr_id <= max_attr_id;
           ++attr_id) {
        values.emplace_back(getTypedValueAtAbsolutePosition(attr_id, tid));
      }
    }
    return new Tuple(std::move(values));
  }

  inline Tuple* getTupleAtAbsolutePositionWithAttributes(
      const tuple_id tid,
      const std::vector<attribute_id> &attributes) const {
    std::vector<TypedValue> values;
    for (const attribute_id attr_id : attributes) {
      values.emplace_back(getTypedValueAtAbsolutePosition(attr_id, tid));
    }
    return new Tuple(std::move(values));
  }

  inline TupleIdSequenceAdapterValueAccessor<PackedTupleStorageSubBlockValueAccessor>*
      createSharedTupleIdSequenceAdapter(const TupleIdSequence &id_sequence) {
    return new TupleIdSequenceAdapterValueAccessor<PackedTupleStorageSubBlockValueAccessor>(
        this,
        id_sequence,
        false);
  }

  inline OrderedTupleIdSequenceAdapterValueAccessor<PackedTupleStorageSubBlockValueAccessor>*
      createSharedOrderedTupleIdSequenceAdapter(const OrderedTupleIdSequence &id_sequence) {
    return new OrderedTupleIdSequenceAdapterValueAccessor<PackedTupleStorageSubBlockValueAccessor>(
        this,
        id_sequence,
        false);
  }

  inline const TupleIdSequence* getTupleIdSequence() const {
    return nullptr;
  }

  // Implementation of virtuals that pass-through to the inline
  // implementations.
  void beginIterationVirtual() override {
    beginIteration();
  }

  bool iterationFinishedVirtual() const override {
    return iterationFinished();
  }

  bool nextVirtual() override {
    return next();
  }

  void previousVirtual() override {
    previous();
  }

  tuple_id getCurrentPositionVirtual() const override {
    return getCurrentPosition();
  }

  tuple_id getEndPositionVirtual() const override {
    return getEndPosition();
  }

  tuple_id getNumTuplesVirtual() const override {
    return getNumTuples();
  }

  const void* getUntypedValueVirtual(const attribute_id attr_id) const override {
    return getUntypedValue(attr_id);
  }

  TypedValue getTypedValueVirtual(const attribute_id attr_id) const override {
    return getTypedValue(attr_id);
  }

  const void* getUntypedValueAtAbsolutePositionVirtual(
      const attribute_id attr_id,
      const tuple_id tid) const override {
    return getUntypedValueAtAbsolutePosition(attr_id, tid);
  }

  TypedValue getTypedValueAtAbsolutePositionVirtual(
      const attribute_id attr_id,
      const tuple_id tid) const override {
    return getTypedValueAtAbsolutePosition(attr_id, tid);
  }

  Tuple* getTupleVirtual() const override {
    return getTuple();
  }

  Tuple* getTupleWithAttributesVirtual(
      const std::vector<attribute_id> &attributes) const override {
    return getTupleWithAttributes(attributes);
  }

  ValueAccessor* createSharedTupleIdSequenceAdapterVirtual(
      const TupleIdSequence &id_sequence) override {
    return createSharedTupleIdSequenceAdapter(id_sequence);
  }

  const TupleIdSequence* getTupleIdSequenceVirtual() const override {
    return getTupleIdSequence();
  }

 private:
  template <typename... HelperArgs>
  PackedTupleStorageSubBlockValueAccessor(
      const CatalogRelationSchema &relation,
      HelperArgs&&... helper_args)
      : relation_(relation),
        helper_(std::forward<HelperArgs>(helper_args)...),
        current_tuple_(-1) {
  }

  const CatalogRelationSchema &relation_;
  HelperT helper_;
  tuple_id current_tuple_;

  friend TupleStorageSubBlockT;

  DISALLOW_COPY_AND_ASSIGN(PackedTupleStorageSubBlockValueAccessor);
};

/** @} */

}  // namespace quickstep

#endif  // QUICKSTEP_STORAGE_VALUE_ACCESSOR_HPP_
