/**
* 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);
    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);
}

boost::optional<bool> IoTDBRpcDataSet::getBooleanByTsBlockColumnIndex(int32_t tsBlockColumnIndex) {
    checkRecord();
    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 (!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 (!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 (!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 (!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_;
}
