// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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.

#pragma once

#include "kudu/common/column_predicate.h"
#include "kudu/common/columnblock.h"

namespace kudu {

// A ColumnMaterializationContext provides a clean interface to the set of
// objects that get passed down to the column iterator and decoders during
// materialization.
//
// Example of path taken:
// MaterializingIterator -> CFileSet::Iterator -> CFileIterator -> BlockDecoder
class ColumnMaterializationContext {
 public:
  ColumnMaterializationContext(size_t col_idx,
                    const ColumnPredicate* pred,
                    ColumnBlock* block,
                    SelectionVector* sel)
    : col_idx_(col_idx),
      pred_(pred),
      block_(block),
      sel_(sel),
      decoder_eval_status_(kNotSet) {
      if (!pred_ || !sel || !block) {
        decoder_eval_status_ = kDecoderEvalNotSupported;
      }
  }

  // Column index in within the projection schema, not the underlying schema.
  const size_t col_idx() { return col_idx_; }

  // Predicate being evaluated.
  const ColumnPredicate* pred() { return pred_; }

  // Destination for copied data.
  ColumnBlock* block() { return block_; }

  // Selection vector reflecting the result of the predicate evaluation.
  // If a given bit is already cleared, that row can be skipped.
  //
  // Required non-null if used by scans, else there will be a nullptr reference
  // when creating a SelectionVectorView around it. Must be large enough to
  // cover the number of rows being scanned.
  SelectionVector* sel() { return sel_; }

  // Checked after returning from the decoder to determine whether or not the
  // block must still be evaluated (on true).
  bool DecoderEvalNotSupported() const {
    return decoder_eval_status_ == kDecoderEvalNotSupported;
  }

  // Checked by CFileIterator::Scan() to determine whether decoder-level
  // evaluation should be attempted (on true).
  bool DecoderEvalNotDisabled() const {
    return decoder_eval_status_ != kDecoderEvalNotSupported;
  }

  // Checked during materialization to determine whether null values should be
  // cleared in the results vector.
  bool EvaluatingIsNull() const {
    return pred_ && pred_->predicate_type() == PredicateType::IsNull;
  }

  // A context should not switch from supporting decoder-level eval to not
  // supporting it, or vice versa.
  //
  // Going from NotSupported to Supported may lead to incorrect results if
  // previously scanned rows materialize values that should not be in the
  // results set. To prevent this, attempts to do this will result in no-ops.
  // This will disable decoder-level evaluation and yield correct values.
  //
  // Should only be called by CopyNextAndEval() of a decoder that supports
  // evaluation.
  void SetDecoderEvalSupported() {
    DCHECK(decoder_eval_status_ != kDecoderEvalNotSupported);
    if (decoder_eval_status_ == kNotSet) {
      DCHECK(sel_ != nullptr && pred_ != nullptr);
      decoder_eval_status_ = kDecoderEvalSupported;
    }
  }

  // Going from Supported to NotSupported may lead to errors if the scan
  // previously evaluated rows that were deemed to be not in the result set.
  // During batch evaluation, these rows would be missing from the buffer,
  // and this could lead to a memory error.
  //
  // Should be called before materializing a column if support has manually
  // been turned off with materializing_iterator_decoder_eval flag, or by
  // CopyNextAndEval() of a decoder that does not support evaluation.
  void SetDecoderEvalNotSupported() {
    CHECK(decoder_eval_status_ != kDecoderEvalSupported);
    decoder_eval_status_ = kDecoderEvalNotSupported;
  }

 private:
  enum DecoderEvalStatus {
    // During scan, will try to evaluate with the decoder, after which the
    // correct status will be set.
    kNotSet = 0,

    // May be set before scanning if the decoder eval flag is set to false
    // or if iterator has deltas associated with it or if the predicate is
    // determined to be ineffective.
    // May be set by decoder during scan if decoder eval is not supported.
    // Once set, scanning will materialize the entire column into the block,
    // leaving evaluation for after the scan.
    kDecoderEvalNotSupported,

    // Is set by a decoder during scan if decoder eval is supported.
    // Once set, the decoder is contractually bound to return with selection
    // vector filled out.
    kDecoderEvalSupported
  };

  const size_t col_idx_;

  const ColumnPredicate* pred_;

  ColumnBlock* block_;

  SelectionVector* const sel_;

  DecoderEvalStatus decoder_eval_status_;
};

} // namespace kudu
