/**
* 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.
 */

#include <algorithm>
#include <ctime>
#include <stdexcept>

#include "IoTDBRpcDataSet.h"

#include <boost/optional/optional.hpp>

#include "Column.h"

const int32_t IoTDBRpcDataSet::startIndex = 2;
const std::string IoTDBRpcDataSet::TimestampColumnName = "Time";
const std::string IoTDBRpcDataSet::DEFAULT_TIME_FORMAT = "default";
const std::string IoTDBRpcDataSet::TIME_PRECISION = "timestamp_precision";
const std::string IoTDBRpcDataSet::MILLISECOND = "ms";
const std::string IoTDBRpcDataSet::MICROSECOND = "us";
const std::string IoTDBRpcDataSet::NANOSECOND = "ns";

IoTDBRpcDataSet::IoTDBRpcDataSet(
    const std::string& sql, const std::vector<std::string>& columnNameList,
    const std::vector<std::string>& columnTypeList,
    const std::map<std::string, int32_t>& columnNameIndex, bool ignoreTimestamp, bool moreData,
    int64_t queryId, int64_t statementId, std::shared_ptr<IClientRPCServiceClient> client,
    int64_t sessionId, const std::vector<std::string>& queryResult, int32_t fetchSize,
    const int64_t timeout, const std::string& zoneId, const std::string& timeFormat,
    int32_t timeFactor, std::vector<int32_t>& columnIndex2TsBlockColumnIndexList)
    : sql_(sql), isClosed_(false), client_(client), fetchSize_(fetchSize), timeout_(timeout),
      hasCachedRecord_(false), lastReadWasNull_(false),
      columnSize_(static_cast<int32_t>(columnNameList.size())), sessionId_(sessionId),
      queryId_(queryId), statementId_(statementId), time_(0), ignoreTimestamp_(ignoreTimestamp),
      moreData_(moreData), queryResult_(queryResult), curTsBlock_(nullptr),
      queryResultSize_(static_cast<int32_t>(queryResult.size())), queryResultIndex_(0),
      tsBlockSize_(0), tsBlockIndex_(-1), timeZoneId_(zoneId), timeFormat_(timeFormat),
      timeFactor_(timeFactor) {
  int columnStartIndex = 1;
  int resultSetColumnSize = columnNameList_.size();
  // newly generated or updated columnIndex2TsBlockColumnIndexList.size() may not be equal to
  // columnNameList.size()
  // so we need startIndexForColumnIndex2TsBlockColumnIndexList to adjust the mapping relation
  int startIndexForColumnIndex2TsBlockColumnIndexList = 0;
  // for Time Column in tree model which should always be the first column and its index for
  // TsBlockColumn is -1
  if (!ignoreTimestamp) {
    columnNameList_.push_back(TimestampColumnName);
    columnTypeList_.push_back("INT64");
    columnName2TsBlockColumnIndexMap_[TimestampColumnName] = -1;
    columnOrdinalMap_[TimestampColumnName] = 1;
    if (!columnIndex2TsBlockColumnIndexList.empty()) {
      columnIndex2TsBlockColumnIndexList.insert(columnIndex2TsBlockColumnIndexList.begin(), -1);
      startIndexForColumnIndex2TsBlockColumnIndexList = 1;
    }
    columnStartIndex++;
    resultSetColumnSize++;
  }

  if (columnIndex2TsBlockColumnIndexList.empty()) {
    columnIndex2TsBlockColumnIndexList.reserve(resultSetColumnSize);
    if (!ignoreTimestamp) {
      startIndexForColumnIndex2TsBlockColumnIndexList = 1;
      columnIndex2TsBlockColumnIndexList.push_back(-1);
    }
    for (size_t i = 0; i < columnNameList.size(); ++i) {
      columnIndex2TsBlockColumnIndexList.push_back(i);
    }
  }

  columnNameList_.insert(columnNameList_.end(), columnNameList.begin(), columnNameList.end());
  columnTypeList_.insert(columnTypeList_.end(), columnTypeList.begin(), columnTypeList.end());

  // Initialize data types for TsBlock columns
  int32_t tsBlockColumnSize = 0;
  for (auto value : columnIndex2TsBlockColumnIndexList) {
    if (value > tsBlockColumnSize) {
      tsBlockColumnSize = value;
    }
  }
  tsBlockColumnSize += 1;
  dataTypeForTsBlockColumn_.resize(tsBlockColumnSize);

  // Populate data types and maps
  for (size_t i = 0; i < columnNameList.size(); i++) {
    auto columnName = columnNameList[i];
    int32_t tsBlockColumnIndex =
        columnIndex2TsBlockColumnIndexList[i + startIndexForColumnIndex2TsBlockColumnIndexList];
    if (tsBlockColumnIndex != -1) {
      dataTypeForTsBlockColumn_[tsBlockColumnIndex] = getDataTypeByStr(columnTypeList[i]);
    }

    if (columnName2TsBlockColumnIndexMap_.find(columnName) ==
        columnName2TsBlockColumnIndexMap_.end()) {
      columnOrdinalMap_[columnName] = i + columnStartIndex;
      columnName2TsBlockColumnIndexMap_[columnName] = tsBlockColumnIndex;
    }
  }

  timePrecision_ = getTimePrecision(timeFactor_);
  columnIndex2TsBlockColumnIndexList_ = columnIndex2TsBlockColumnIndexList;
}

IoTDBRpcDataSet::~IoTDBRpcDataSet() {
  if (!isClosed_) {
    close();
  }
}

bool IoTDBRpcDataSet::next() {
  if (hasCachedBlock()) {
    lastReadWasNull_ = false;
    constructOneRow();
    return true;
  }

  if (hasCachedByteBuffer()) {
    constructOneTsBlock();
    constructOneRow();
    return true;
  }

  if (moreData_) {
    bool hasResultSet = fetchResults();
    if (hasResultSet && hasCachedByteBuffer()) {
      constructOneTsBlock();
      constructOneRow();
      return true;
    }
  }

  close();
  return false;
}

void IoTDBRpcDataSet::close(bool forceClose) {
  if ((!forceClose) && isClosed_) {
    return;
  }
  TSCloseOperationReq closeReq;
  closeReq.__set_sessionId(sessionId_);
  closeReq.__set_statementId(statementId_);
  closeReq.__set_queryId(queryId_);
  TSStatus tsStatus;
  try {
    client_->closeOperation(tsStatus, closeReq);
    RpcUtils::verifySuccess(tsStatus);
  } catch (const TTransportException& e) {
    log_debug(e.what());
    throw IoTDBConnectionException(e.what());
  } catch (const IoTDBException& e) {
    log_debug(e.what());
    throw;
  } catch (exception& e) {
    log_debug(e.what());
    throw IoTDBException(e.what());
  }
  isClosed_ = true;
  client_ = nullptr;
}

bool IoTDBRpcDataSet::fetchResults() {
  if (isClosed_) {
    throw IoTDBException("This data set is already closed");
  }

  TSFetchResultsReq req;
  req.__set_sessionId(sessionId_);
  req.__set_statement(sql_);
  req.__set_fetchSize(fetchSize_);
  req.__set_queryId(queryId_);
  req.__set_isAlign(true);
  req.__set_timeout(timeout_);
  TSFetchResultsResp resp;
  client_->fetchResultsV2(resp, req);
  RpcUtils::verifySuccess(resp.status);
  moreData_ = resp.moreData;
  if (!resp.hasResultSet) {
    close();
  } else {
    queryResult_ = resp.queryResult;
    queryResultIndex_ = 0;
    if (!queryResult_.empty()) {
      queryResultSize_ = queryResult_.size();
    } else {
      queryResultSize_ = 0;
    }
    tsBlockIndex_ = -1;
    tsBlockSize_ = 0;
  }
  return resp.hasResultSet;
}

void IoTDBRpcDataSet::constructOneRow() {
  tsBlockIndex_++;
  hasCachedRecord_ = true;
  time_ = curTsBlock_->getTimeColumn()->getLong(tsBlockIndex_);
}

void IoTDBRpcDataSet::constructOneTsBlock() {
  lastReadWasNull_ = false;
  const auto& curTsBlockBytes = queryResult_[queryResultIndex_];
  queryResultIndex_++;
  curTsBlock_ = TsBlock::deserialize(curTsBlockBytes);
  tsBlockIndex_ = -1;
  tsBlockSize_ = curTsBlock_->getPositionCount();
}

bool IoTDBRpcDataSet::isNullByIndex(int32_t columnIndex) {
  int32_t index = getTsBlockColumnIndexForColumnIndex(columnIndex);
  return isNull(index, tsBlockIndex_);
}

bool IoTDBRpcDataSet::isNullByColumnName(const std::string& columnName) {
  int32_t index = getTsBlockColumnIndexForColumnName(columnName);
  return isNull(index, tsBlockIndex_);
}

bool IoTDBRpcDataSet::isNull(int32_t index, int32_t rowNum) {
  return index >= 0 && curTsBlock_->getColumn(index)->isNull(rowNum);
}

boost::optional<bool> IoTDBRpcDataSet::getBooleanByIndex(int32_t columnIndex) {
  int32_t index = getTsBlockColumnIndexForColumnIndex(columnIndex);
  return getBooleanByTsBlockColumnIndex(index);
}

boost::optional<bool> IoTDBRpcDataSet::getBoolean(const std::string& columnName) {
  int32_t index = getTsBlockColumnIndexForColumnName(columnName);
  return getBooleanByTsBlockColumnIndex(index);
}

// Note: tsBlockColumnIndex < 0 indicates the time pseudo-column in tree model.
// Only getLong and getString support reading the time column directly.
// All other typed getters throw IoTDBException to prevent undefined behavior
// from accessing valueColumns_ with a negative index.
boost::optional<bool> IoTDBRpcDataSet::getBooleanByTsBlockColumnIndex(int32_t tsBlockColumnIndex) {
  checkRecord();
  if (tsBlockColumnIndex < 0) {
    throw IoTDBException("Cannot read boolean from time column");
  }
  if (!isNull(tsBlockColumnIndex, tsBlockIndex_)) {
    lastReadWasNull_ = false;
    return curTsBlock_->getColumn(tsBlockColumnIndex)->getBoolean(tsBlockIndex_);
  } else {
    lastReadWasNull_ = true;
    return boost::none;
  }
}

boost::optional<double> IoTDBRpcDataSet::getDoubleByIndex(int32_t columnIndex) {
  int32_t index = getTsBlockColumnIndexForColumnIndex(columnIndex);
  return getDoubleByTsBlockColumnIndex(index);
}

boost::optional<double> IoTDBRpcDataSet::getDouble(const std::string& columnName) {
  int32_t index = getTsBlockColumnIndexForColumnName(columnName);
  return getDoubleByTsBlockColumnIndex(index);
}

boost::optional<double> IoTDBRpcDataSet::getDoubleByTsBlockColumnIndex(int32_t tsBlockColumnIndex) {
  checkRecord();
  if (tsBlockColumnIndex < 0) {
    throw IoTDBException("Cannot read double from time column");
  }
  if (!isNull(tsBlockColumnIndex, tsBlockIndex_)) {
    lastReadWasNull_ = false;
    return curTsBlock_->getColumn(tsBlockColumnIndex)->getDouble(tsBlockIndex_);
  } else {
    lastReadWasNull_ = true;
    return boost::none;
  }
}

boost::optional<float> IoTDBRpcDataSet::getFloatByIndex(int32_t columnIndex) {
  int32_t index = getTsBlockColumnIndexForColumnIndex(columnIndex);
  return getFloatByTsBlockColumnIndex(index);
}

boost::optional<float> IoTDBRpcDataSet::getFloat(const std::string& columnName) {
  int32_t index = getTsBlockColumnIndexForColumnName(columnName);
  return getFloatByTsBlockColumnIndex(index);
}

boost::optional<float> IoTDBRpcDataSet::getFloatByTsBlockColumnIndex(int32_t tsBlockColumnIndex) {
  checkRecord();
  if (tsBlockColumnIndex < 0) {
    throw IoTDBException("Cannot read float from time column");
  }
  if (!isNull(tsBlockColumnIndex, tsBlockIndex_)) {
    lastReadWasNull_ = false;
    return curTsBlock_->getColumn(tsBlockColumnIndex)->getFloat(tsBlockIndex_);
  } else {
    lastReadWasNull_ = true;
    return boost::none;
  }
}

boost::optional<int32_t> IoTDBRpcDataSet::getIntByIndex(int32_t columnIndex) {
  int32_t index = getTsBlockColumnIndexForColumnIndex(columnIndex);
  return getIntByTsBlockColumnIndex(index);
}

boost::optional<int32_t> IoTDBRpcDataSet::getInt(const std::string& columnName) {
  int32_t index = getTsBlockColumnIndexForColumnName(columnName);
  return getIntByTsBlockColumnIndex(index);
}

boost::optional<int32_t> IoTDBRpcDataSet::getIntByTsBlockColumnIndex(int32_t tsBlockColumnIndex) {
  checkRecord();
  if (tsBlockColumnIndex < 0) {
    throw IoTDBException("Cannot read int32 from time column");
  }
  if (!isNull(tsBlockColumnIndex, tsBlockIndex_)) {
    lastReadWasNull_ = false;
    TSDataType::TSDataType dataType = curTsBlock_->getColumn(tsBlockColumnIndex)->getDataType();
    if (dataType == TSDataType::INT64) {
      return static_cast<int32_t>(
          curTsBlock_->getColumn(tsBlockColumnIndex)->getLong(tsBlockIndex_));
    }
    return curTsBlock_->getColumn(tsBlockColumnIndex)->getInt(tsBlockIndex_);
  } else {
    lastReadWasNull_ = true;
    return boost::none;
  }
}

boost::optional<int64_t> IoTDBRpcDataSet::getLongByIndex(int32_t columnIndex) {
  int32_t index = getTsBlockColumnIndexForColumnIndex(columnIndex);
  return getLongByTsBlockColumnIndex(index);
}

boost::optional<int64_t> IoTDBRpcDataSet::getLong(const std::string& columnName) {
  int32_t index = getTsBlockColumnIndexForColumnName(columnName);
  return getLongByTsBlockColumnIndex(index);
}

boost::optional<int64_t> IoTDBRpcDataSet::getLongByTsBlockColumnIndex(int32_t tsBlockColumnIndex) {
  checkRecord();
  if (tsBlockColumnIndex < 0) {
    lastReadWasNull_ = false;
    return curTsBlock_->getTimeByIndex(tsBlockIndex_);
  }
  if (!isNull(tsBlockColumnIndex, tsBlockIndex_)) {
    lastReadWasNull_ = false;
    TSDataType::TSDataType dataType = curTsBlock_->getColumn(tsBlockColumnIndex)->getDataType();
    if (dataType == TSDataType::INT32) {
      return static_cast<int64_t>(
          curTsBlock_->getColumn(tsBlockColumnIndex)->getInt(tsBlockIndex_));
    }
    return curTsBlock_->getColumn(tsBlockColumnIndex)->getLong(tsBlockIndex_);
  } else {
    lastReadWasNull_ = true;
    return boost::none;
  }
}

std::shared_ptr<Binary> IoTDBRpcDataSet::getBinaryByIndex(int32_t columnIndex) {
  int32_t index = getTsBlockColumnIndexForColumnIndex(columnIndex);
  return getBinaryByTsBlockColumnIndex(index);
}

std::shared_ptr<Binary> IoTDBRpcDataSet::getBinary(const std::string& columnName) {
  int32_t index = getTsBlockColumnIndexForColumnName(columnName);
  return getBinaryByTsBlockColumnIndex(index);
}

std::shared_ptr<Binary> IoTDBRpcDataSet::getBinaryByTsBlockColumnIndex(int32_t tsBlockColumnIndex) {
  checkRecord();
  if (tsBlockColumnIndex < 0) {
    throw IoTDBException("Cannot read binary from time column");
  }
  if (!isNull(tsBlockColumnIndex, tsBlockIndex_)) {
    lastReadWasNull_ = false;
    return curTsBlock_->getColumn(tsBlockColumnIndex)->getBinary(tsBlockIndex_);
  } else {
    lastReadWasNull_ = true;
    return nullptr;
  }
}

boost::optional<std::string> IoTDBRpcDataSet::getStringByIndex(int32_t columnIndex) {
  int32_t index = getTsBlockColumnIndexForColumnIndex(columnIndex);
  return getStringByTsBlockColumnIndex(index);
}

boost::optional<std::string> IoTDBRpcDataSet::getString(const std::string& columnName) {
  int32_t index = getTsBlockColumnIndexForColumnName(columnName);
  return getStringByTsBlockColumnIndex(index);
}

boost::optional<std::string>
IoTDBRpcDataSet::getStringByTsBlockColumnIndex(int32_t tsBlockColumnIndex) {
  checkRecord();
  if (tsBlockColumnIndex < 0) {
    int64_t timestamp = curTsBlock_->getTimeByIndex(tsBlockIndex_);
    return std::to_string(timestamp);
  }
  if (isNull(tsBlockColumnIndex, tsBlockIndex_)) {
    lastReadWasNull_ = true;
    return boost::none;
  }
  lastReadWasNull_ = false;
  return getStringByTsBlockColumnIndexAndDataType(
      tsBlockColumnIndex, getDataTypeByTsBlockColumnIndex(tsBlockColumnIndex));
}

std::string
IoTDBRpcDataSet::getStringByTsBlockColumnIndexAndDataType(int32_t index,
                                                          TSDataType::TSDataType tsDataType) {
  switch (tsDataType) {
  case TSDataType::BOOLEAN:
    return std::to_string(curTsBlock_->getColumn(index)->getBoolean(tsBlockIndex_));
  case TSDataType::INT32:
    return std::to_string(curTsBlock_->getColumn(index)->getInt(tsBlockIndex_));
  case TSDataType::INT64:
    return std::to_string(curTsBlock_->getColumn(index)->getLong(tsBlockIndex_));
  case TSDataType::TIMESTAMP: {
    int64_t value = curTsBlock_->getColumn(index)->getLong(tsBlockIndex_);
    return formatDatetime(timeFormat_, timePrecision_, value, timeZoneId_);
  }
  case TSDataType::FLOAT:
    return std::to_string(curTsBlock_->getColumn(index)->getFloat(tsBlockIndex_));
  case TSDataType::DOUBLE:
    return std::to_string(curTsBlock_->getColumn(index)->getDouble(tsBlockIndex_));
  case TSDataType::TEXT:
  case TSDataType::STRING:
  case TSDataType::OBJECT:
  case TSDataType::BLOB: {
    auto binary = curTsBlock_->getColumn(index)->getBinary(tsBlockIndex_);
    return binary->getStringValue();
  }
  case TSDataType::DATE: {
    int32_t value = curTsBlock_->getColumn(index)->getInt(tsBlockIndex_);
    auto date = parseIntToDate(value);
    return boost::gregorian::to_iso_extended_string(date);
  }
  default:
    return "";
  }
}

boost::optional<int64_t> IoTDBRpcDataSet::getTimestampByIndex(int32_t columnIndex) {
  int32_t index = getTsBlockColumnIndexForColumnIndex(columnIndex);
  return getTimestampByTsBlockColumnIndex(index);
}

boost::optional<int64_t> IoTDBRpcDataSet::getTimestamp(const std::string& columnName) {
  int32_t index = getTsBlockColumnIndexForColumnName(columnName);
  return getTimestampByTsBlockColumnIndex(index);
}

boost::optional<int64_t>
IoTDBRpcDataSet::getTimestampByTsBlockColumnIndex(int32_t tsBlockColumnIndex) {
  return getLongByTsBlockColumnIndex(tsBlockColumnIndex);
}

boost::optional<boost::gregorian::date> IoTDBRpcDataSet::getDateByIndex(int32_t columnIndex) {
  int32_t index = getTsBlockColumnIndexForColumnIndex(columnIndex);
  return getDateByTsBlockColumnIndex(index);
}

boost::optional<boost::gregorian::date> IoTDBRpcDataSet::getDate(const std::string& columnName) {
  int32_t index = getTsBlockColumnIndexForColumnName(columnName);
  return getDateByTsBlockColumnIndex(index);
}

boost::optional<boost::gregorian::date>
IoTDBRpcDataSet::getDateByTsBlockColumnIndex(int32_t tsBlockColumnIndex) {
  auto value = getIntByTsBlockColumnIndex(tsBlockColumnIndex);
  if (!value.is_initialized()) {
    return boost::none;
  }
  return parseIntToDate(value.value());
}

TSDataType::TSDataType IoTDBRpcDataSet::getDataTypeByIndex(int32_t columnIndex) {
  int32_t index = getTsBlockColumnIndexForColumnIndex(columnIndex);
  return getDataTypeByTsBlockColumnIndex(index);
}

TSDataType::TSDataType IoTDBRpcDataSet::getDataType(const std::string& columnName) {
  int32_t index = getTsBlockColumnIndexForColumnName(columnName);
  return getDataTypeByTsBlockColumnIndex(index);
}

int32_t IoTDBRpcDataSet::getTsBlockColumnIndexForColumnIndex(int32_t columnIndex) {
  const int32_t adjusted_index = columnIndex - 1;
  if (adjusted_index >= static_cast<int32_t>(columnIndex2TsBlockColumnIndexList_.size()) ||
      adjusted_index < 0) {
    throw std::out_of_range("Index " + std::to_string(adjusted_index) + " out of range [0, " +
                            std::to_string(columnIndex2TsBlockColumnIndexList_.size()) + ")");
  }
  return columnIndex2TsBlockColumnIndexList_[adjusted_index];
}

TSDataType::TSDataType
IoTDBRpcDataSet::getDataTypeByTsBlockColumnIndex(int32_t tsBlockColumnIndex) {
  if (tsBlockColumnIndex < 0) {
    return TSDataType::TIMESTAMP;
  } else {
    return dataTypeForTsBlockColumn_[tsBlockColumnIndex];
  }
}

int32_t IoTDBRpcDataSet::findColumn(const std::string& columnName) {
  auto it = columnOrdinalMap_.find(columnName);
  if (it != columnOrdinalMap_.end()) {
    return it->second;
  }
  return -1;
}

std::string IoTDBRpcDataSet::findColumnNameByIndex(int32_t columnIndex) {
  if (columnIndex <= 0) {
    throw IoTDBException("column index should start from 1");
  }
  if (columnIndex > static_cast<int32_t>(columnNameList_.size())) {
    throw IoTDBException("Column index " + std::to_string(columnIndex) +
                         " is out of range. Valid range is 0 to " +
                         std::to_string(columnNameList_.size() - 1));
  }
  return columnNameList_[columnIndex - 1];
}

int32_t IoTDBRpcDataSet::getTsBlockColumnIndexForColumnName(const std::string& columnName) {
  auto it = columnName2TsBlockColumnIndexMap_.find(columnName);
  if (it == columnName2TsBlockColumnIndexMap_.end()) {
    throw IoTDBException("unknown column name: " + columnName);
  }
  return it->second;
}

void IoTDBRpcDataSet::checkRecord() {
  if (queryResultIndex_ > queryResultSize_ || tsBlockIndex_ >= tsBlockSize_ ||
      queryResult_.empty() || !curTsBlock_) {
    throw IoTDBException("no record remains");
  }
}

int32_t IoTDBRpcDataSet::getValueColumnStartIndex() const {
  return ignoreTimestamp_ ? 0 : 1;
}

int32_t IoTDBRpcDataSet::getColumnSize() const {
  return static_cast<int32_t>(columnNameList_.size());
}

const std::vector<std::string>& IoTDBRpcDataSet::getColumnTypeList() const {
  return columnTypeList_;
}

const std::vector<std::string>& IoTDBRpcDataSet::getColumnNameList() const {
  return columnNameList_;
}

bool IoTDBRpcDataSet::isClosed() const {
  return isClosed_;
}

int32_t IoTDBRpcDataSet::getFetchSize() const {
  return fetchSize_;
}

void IoTDBRpcDataSet::setFetchSize(int32_t fetchSize) {
  fetchSize_ = fetchSize;
}

bool IoTDBRpcDataSet::hasCachedRecord() const {
  return hasCachedRecord_;
}

void IoTDBRpcDataSet::setHasCachedRecord(bool hasCachedRecord) {
  hasCachedRecord_ = hasCachedRecord;
}

bool IoTDBRpcDataSet::isLastReadWasNull() const {
  return lastReadWasNull_;
}

int64_t IoTDBRpcDataSet::getCurrentRowTime() const {
  return time_;
}

bool IoTDBRpcDataSet::isIgnoreTimestamp() const {
  return ignoreTimestamp_;
}

bool IoTDBRpcDataSet::hasCachedBlock() const {
  return curTsBlock_ && tsBlockIndex_ < tsBlockSize_ - 1;
}

bool IoTDBRpcDataSet::hasCachedByteBuffer() const {
  return !queryResult_.empty() && queryResultIndex_ < queryResultSize_;
}
