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

package org.apache.carbondata.core.scan.filter.executer;

import java.io.IOException;
import java.util.BitSet;

import org.apache.carbondata.core.constants.CarbonCommonConstants;
import org.apache.carbondata.core.datastore.block.SegmentProperties;
import org.apache.carbondata.core.datastore.chunk.DimensionColumnPage;
import org.apache.carbondata.core.datastore.chunk.impl.DimensionRawColumnChunk;
import org.apache.carbondata.core.metadata.datatype.DataTypes;
import org.apache.carbondata.core.metadata.schema.table.column.CarbonDimension;
import org.apache.carbondata.core.scan.expression.Expression;
import org.apache.carbondata.core.scan.expression.conditional.GreaterThanEqualToExpression;
import org.apache.carbondata.core.scan.expression.conditional.GreaterThanExpression;
import org.apache.carbondata.core.scan.expression.conditional.LessThanEqualToExpression;
import org.apache.carbondata.core.scan.expression.conditional.LessThanExpression;
import org.apache.carbondata.core.scan.filter.FilterUtil;
import org.apache.carbondata.core.scan.filter.intf.RowIntf;
import org.apache.carbondata.core.scan.filter.resolver.resolverinfo.DimColumnResolvedFilterInfo;
import org.apache.carbondata.core.scan.processor.RawBlockletColumnChunks;
import org.apache.carbondata.core.util.BitSetGroup;
import org.apache.carbondata.core.util.ByteUtil;
import org.apache.carbondata.core.util.CarbonUtil;

/**
 * This Class get a Min And Max value of a RANGE expression. Finds out if scan is required
 * for this Range. Also search the data block and set the required bitsets which falls within
 * the Range of the RANGE Expression.
 */
public class RangeValueFilterExecutorImpl implements FilterExecutor {

  private DimColumnResolvedFilterInfo dimColEvaluatorInfo;
  private Expression exp;
  private byte[][] filterRangesValues;
  private SegmentProperties segmentProperties;
  private boolean isDefaultValuePresentInFilter;

  /**
   * flag to check whether the filter dimension is present in current block list of dimensions.
   * Applicable for restructure scenarios
   */
  private boolean isDimensionPresentInCurrentBlock;
  private boolean lessThanExp;
  private boolean lessThanEqualExp;
  private boolean greaterThanExp;
  private boolean greaterThanEqualExp;
  private boolean startBlockMinIsDefaultStart;
  private boolean endBlockMaxisDefaultEnd;
  private boolean isRangeFullyCoverBlock;
  private boolean isNaturalSorted;

  public RangeValueFilterExecutorImpl(DimColumnResolvedFilterInfo dimColEvaluatorInfo,
      Expression exp, byte[][] filterRangeValues, SegmentProperties segmentProperties) {

    this.dimColEvaluatorInfo = dimColEvaluatorInfo;
    this.exp = exp;
    this.segmentProperties = segmentProperties;
    this.filterRangesValues = filterRangeValues;
    this.lessThanExp = isLessThan();
    this.lessThanEqualExp = isLessThanEqualTo();
    this.greaterThanExp = isGreaterThan();
    this.greaterThanEqualExp = isGreaterThanEqualTo();
    startBlockMinIsDefaultStart = false;
    endBlockMaxisDefaultEnd = false;
    isRangeFullyCoverBlock = false;
    initDimensionChunkIndexes();
    ifDefaultValueMatchesFilter();
    if (isDimensionPresentInCurrentBlock) {
      isNaturalSorted = dimColEvaluatorInfo.getDimension().isUseInvertedIndex()
          && dimColEvaluatorInfo.getDimension().isSortColumn();
    }
  }

  /**
   * This method will initialize the dimension info for the current block to be
   * used for filtering the data
   */
  private void initDimensionChunkIndexes() {
    // find the dimension in the current block dimensions list
    CarbonDimension dimensionFromCurrentBlock =
        segmentProperties.getDimensionFromCurrentBlock(dimColEvaluatorInfo.getDimension());
    if (null != dimensionFromCurrentBlock) {
      dimColEvaluatorInfo.setColumnIndex(dimensionFromCurrentBlock.getOrdinal());
      isDimensionPresentInCurrentBlock = true;
    }
  }

  /**
   * This method will check whether default value is present in the given filter values
   */
  private void ifDefaultValueMatchesFilter() {
    isDefaultValuePresentInFilter = false;
    if (!this.isDimensionPresentInCurrentBlock && null != filterRangesValues) {
      CarbonDimension dimension = this.dimColEvaluatorInfo.getDimension();
      byte[] defaultValue = dimension.getDefaultValue();
      if (null != defaultValue) {
        int minCompare =
            FilterUtil.compareValues(filterRangesValues[0], defaultValue, dimension, true);
        int maxCompare =
            FilterUtil.compareValues(filterRangesValues[1], defaultValue, dimension, false);

        if (((greaterThanExp && maxCompare > 0) || (greaterThanEqualExp && maxCompare >= 0)) && (
            (lessThanExp && minCompare > 0) || (lessThanEqualExp && minCompare >= 0))) {
          isDefaultValuePresentInFilter = true;
        }
      }
    }
  }

  /**
   * Method to apply the filter.
   * @param rawBlockletColumnChunks
   * @return
   * @throws IOException
   */
  public BitSetGroup applyFilter(RawBlockletColumnChunks rawBlockletColumnChunks,
      boolean useBitsetPipeLine) throws IOException {
    return applyNoAndDirectFilter(rawBlockletColumnChunks, useBitsetPipeLine);
  }

  @Override
  public BitSet prunePages(RawBlockletColumnChunks blockChunkHolder)
      throws IOException {
    // In case of Alter Table Add and Delete Columns the isDimensionPresentInCurrentBlock can be
    // false, in that scenario the default values of the column should be shown.
    // select all rows if dimension does not exists in the current block
    if (!isDimensionPresentInCurrentBlock) {
      int numberOfPages = blockChunkHolder.getDataBlock().numberOfPages();
      BitSet bitSet = new BitSet();
      bitSet.set(0, numberOfPages);
      return bitSet;
    }

    int chunkIndex = segmentProperties.getDimensionOrdinalToChunkMapping()
        .get(dimColEvaluatorInfo.getColumnIndex());

    if (null == blockChunkHolder.getDimensionRawColumnChunks()[chunkIndex]) {
      blockChunkHolder.getDimensionRawColumnChunks()[chunkIndex] = blockChunkHolder.getDataBlock()
          .readDimensionChunk(blockChunkHolder.getFileReader(), chunkIndex);
    }

    DimensionRawColumnChunk rawColumnChunk =
        blockChunkHolder.getDimensionRawColumnChunks()[chunkIndex];
    BitSet bitSet = new BitSet(rawColumnChunk.getPagesCount());
    for (int i = 0; i < rawColumnChunk.getPagesCount(); i++) {
      if (rawColumnChunk.getMaxValues() != null) {
        if (isScanRequired(rawColumnChunk.getMinValues()[i], rawColumnChunk.getMaxValues()[i],
            this.filterRangesValues, rawColumnChunk.getMinMaxFlagArray()[i])) {
          bitSet.set(i);
        }
      } else {
        bitSet.set(i);
      }
    }
    return bitSet;

  }

  /**
   * apply range filter on a row
   */
  public boolean applyFilter(RowIntf value, int dimOrdinalMax) {

    byte[] col = (byte[]) value.getVal(dimColEvaluatorInfo.getDimension().getOrdinal());
    byte[][] filterValues = this.filterRangesValues;

    if (isDimensionPresentInCurrentBlock) {
      boolean result;
      if (greaterThanExp) {
        result = ByteUtil.compare(filterValues[0], col) < 0;
      } else {
        result = ByteUtil.compare(filterValues[0], col) <= 0;
      }

      if (result) {
        if (lessThanExp) {
          return ByteUtil.compare(filterValues[1], col) > 0;
        } else {
          return ByteUtil.compare(filterValues[1], col) >= 0;
        }
      }
    }
    return false;
  }

  /**
   * Method to find presence of LessThan Expression.
   * @return
   */
  private boolean isLessThan() {
    for (Expression result : this.exp.getChildren()) {
      if (result instanceof LessThanExpression) {
        return true;
      }
    }
    return false;
  }

  /**
   * Method to find presence of LessThanEqualTo Expression.
   * @return
   */
  private boolean isLessThanEqualTo() {
    for (Expression result : this.exp.getChildren()) {
      if (result instanceof LessThanEqualToExpression) {
        return true;
      }
    }
    return false;
  }

  /**
   * Method to find presence of GreaterThan Expression.
   * @return
   */
  private boolean isGreaterThan() {
    for (Expression result : this.exp.getChildren()) {
      if (result instanceof GreaterThanExpression) {
        return true;
      }
    }
    return false;
  }

  /**
   * Method to find presence of GreaterThanEqual Expression.
   * @return
   */
  private boolean isGreaterThanEqualTo() {
    for (Expression result : this.exp.getChildren()) {
      if (result instanceof GreaterThanEqualToExpression) {
        return true;
      }
    }
    return false;
  }

  /**
   * Method to identify if scanning of Data Block required or not by comparing the Block Min and Max
   * values and comparing them with filter min and max value.
   * @param blockMinValue
   * @param blockMaxValue
   * @param filterValues
   * @return
   */
  public boolean isScanRequired(byte[] blockMinValue, byte[] blockMaxValue, byte[][] filterValues,
      boolean isMinMaxSet) {
    if (!isMinMaxSet) {
      // scan complete data if min max is not written for a given column
      return true;
    }
    boolean isScanRequired = true;
    isRangeFullyCoverBlock = false;
    startBlockMinIsDefaultStart = false;
    endBlockMaxisDefaultEnd = false;

    /*
    For understanding the below logic kept the value evaluation code intact.
    int filterMinLessThanBlockMin =
        ByteUtil.UnsafeComparer.INSTANCE.compareTo(blockMinValue, filterValues[0]);
    int filterMaxLessThanBlockMin =
        ByteUtil.UnsafeComparer.INSTANCE.compareTo(blockMinValue, filterValues[1]);

    int filterMinGreaterThanBlockMax =
        ByteUtil.UnsafeComparer.INSTANCE.compareTo(filterValues[0], blockMaxValue);
    int filterMaxGreaterThanBlockMax =
        ByteUtil.UnsafeComparer.INSTANCE.compareTo(filterValues[1], blockMaxValue);
     */

    // if any filter value is in range than this block needs to be
    // scanned less than equal to max range.
    // There are 4 cases which has been explicitly handled.
    // case A: Outside Boundary > No Scan required
    //                                                Block Min <---------->  Block Max
    //        Filter Min <----------> Filter Max
    // case B: Filter Overlaps Upper Part Block then Block Start Scan Becomes StartIndex of Block.
    //                         Block Min <-----------------> Block Max
    //   Filter Min <-------------------------> Filter Min
    // Case C: Filter Overlaps Lower Part of Block then Block End Scan becomes Number Of Rows - 1
    //         Block Min <-------------------------> Block Max
    //                          Filter Min <--------------------------> Filter Max
    // Case D: Filter Values Completely overlaps Block Min and Max then all bits are set.
    //                       Block Min <-----------------------> Block Max
    //         Filter Min <-----------------------------------------------> Filter Max
    // for no dictionary measure column comparison can be done
    // on the original data as like measure column

    if (isDimensionPresentInCurrentBlock) {
      CarbonDimension carbonDimension = dimColEvaluatorInfo.getDimension();
      if (((lessThanExp) && (
          FilterUtil.compareValues(filterValues[1], blockMinValue, carbonDimension, true) >= 0))
          || ((lessThanEqualExp) && (
          FilterUtil.compareValues(filterValues[1], blockMinValue, carbonDimension, true) > 0)) || (
          (greaterThanExp) && (
              FilterUtil.compareValues(filterValues[0], blockMaxValue, carbonDimension, false)
                  >= 0)) || ((greaterThanEqualExp) && (
          FilterUtil.compareValues(filterValues[0], blockMaxValue, carbonDimension, false) > 0))) {
        // completely out of block boundary
        isScanRequired = false;
      } else {
        if (((greaterThanExp) && (
            FilterUtil.compareValues(filterValues[0], blockMinValue, carbonDimension, true) > 0))
            || ((greaterThanEqualExp) && (
            FilterUtil.compareValues(filterValues[0], blockMinValue, carbonDimension, true)
                >= 0))) {
          startBlockMinIsDefaultStart = true;
        }

        if (((lessThanExp) && (
            FilterUtil.compareValues(filterValues[1], blockMaxValue, carbonDimension, false) > 0))
            || ((lessThanEqualExp) && (
            FilterUtil.compareValues(filterValues[1], blockMaxValue, carbonDimension, false)
                >= 0))) {
          endBlockMaxisDefaultEnd = true;
        }

        if (startBlockMinIsDefaultStart && endBlockMaxisDefaultEnd) {
          isRangeFullyCoverBlock = true;
        }
      }
      return isScanRequired;
    } else {
      return isDefaultValuePresentInFilter;
    }
  }

  /**
   * Method checks is the scan lies within the range values or not.
   * @param blockMaxValue
   * @param blockMinValue
   * @return
   */
  @Override
  public BitSet isScanRequired(byte[][] blockMaxValue, byte[][] blockMinValue,
      boolean[] isMinMaxSet) {
    BitSet bitSet = new BitSet(1);
    byte[][] filterValues = this.filterRangesValues;
    int columnIndex = this.dimColEvaluatorInfo.getColumnIndexInMinMaxByteArray();
    boolean isScanRequired =
        columnIndex >= blockMinValue.length || isScanRequired(blockMinValue[columnIndex],
            blockMaxValue[columnIndex], filterValues, isMinMaxSet[columnIndex]);
    if (isScanRequired) {
      bitSet.set(0);
    }
    return bitSet;
  }

  /**
   * Method to apply the Range Filter.
   * @param blockChunkHolder
   * @return
   * @throws IOException
   */
  private BitSetGroup applyNoAndDirectFilter(RawBlockletColumnChunks blockChunkHolder,
      boolean useBitsetPipeLine) throws IOException {

    // In case of Alter Table Add and Delete Columns the isDimensionPresentInCurrentBlock can be
    // false, in that scenario the default values of the column should be shown.
    // select all rows if dimension does not exists in the current block
    if (!isDimensionPresentInCurrentBlock) {
      int numberOfRows = blockChunkHolder.getDataBlock().numRows();
      return FilterUtil.createBitSetGroupWithDefaultValue(
          blockChunkHolder.getDataBlock().numberOfPages(), numberOfRows, true);
    }

    int chunkIndex = segmentProperties.getDimensionOrdinalToChunkMapping()
        .get(dimColEvaluatorInfo.getColumnIndex());

    if (null == blockChunkHolder.getDimensionRawColumnChunks()[chunkIndex]) {
      blockChunkHolder.getDimensionRawColumnChunks()[chunkIndex] =
          blockChunkHolder.getDataBlock().readDimensionChunk(
              blockChunkHolder.getFileReader(), chunkIndex);
    }

    DimensionRawColumnChunk rawColumnChunk =
        blockChunkHolder.getDimensionRawColumnChunks()[chunkIndex];
    BitSetGroup bitSetGroup = new BitSetGroup(rawColumnChunk.getPagesCount());
    FilterExecutor filterExecutor = null;
    boolean isExclude = false;
    for (int i = 0; i < rawColumnChunk.getPagesCount(); i++) {
      if (rawColumnChunk.getMaxValues() != null) {
        if (isScanRequired(rawColumnChunk.getMinValues()[i], rawColumnChunk.getMaxValues()[i],
            this.filterRangesValues, rawColumnChunk.getMinMaxFlagArray()[i])) {
          if (isRangeFullyCoverBlock) {
            // Set all the bits in this case as filter Min Max values cover the whole block.
            BitSet bitSet = new BitSet(rawColumnChunk.getRowCount()[i]);
            bitSet.flip(0, rawColumnChunk.getRowCount()[i]);
            bitSetGroup.setBitSet(bitSet, i);
          } else {
            BitSet bitSet;
            DimensionColumnPage dimensionColumnPage = rawColumnChunk.decodeColumnPage(i);
            if (null != rawColumnChunk.getLocalDictionary()) {
              if (null == filterExecutor) {
                filterExecutor = FilterUtil
                    .getFilterExecutorForRangeFilters(rawColumnChunk, exp, isNaturalSorted);
                if (filterExecutor instanceof ExcludeFilterExecutorImpl) {
                  isExclude = true;
                }
              }
              if (!isExclude) {
                bitSet = ((IncludeFilterExecutorImpl) filterExecutor)
                    .getFilteredIndexes(dimensionColumnPage,
                        rawColumnChunk.getRowCount()[i], useBitsetPipeLine,
                        blockChunkHolder.getBitSetGroup(), i);
              } else {
                bitSet = ((ExcludeFilterExecutorImpl) filterExecutor)
                    .getFilteredIndexes(dimensionColumnPage,
                        rawColumnChunk.getRowCount()[i], useBitsetPipeLine,
                        blockChunkHolder.getBitSetGroup(), i);
              }
            } else {
              bitSet = getFilteredIndexes(dimensionColumnPage,
                  rawColumnChunk.getRowCount()[i]);
            }
            bitSetGroup.setBitSet(bitSet, i);
          }
        }
      } else {
        BitSet bitSet = getFilteredIndexes(rawColumnChunk.decodeColumnPage(i),
            rawColumnChunk.getRowCount()[i]);
        bitSetGroup.setBitSet(bitSet, i);
      }
    }
    return bitSetGroup;
  }

  private BitSet getFilteredIndexes(DimensionColumnPage dimensionColumnPage,
      int numberOfRows) {
    if (dimensionColumnPage.isExplicitSorted()) {
      return setFilteredIndexToBitSetWithColumnIndex(dimensionColumnPage, numberOfRows);
    }
    return setFilteredIndexToBitSet(dimensionColumnPage, numberOfRows);
  }

  /**
   * Method will scan the block and finds the range start index from which all members
   * will be considered for applying range filters. this method will be called if the
   * column is not supported by default so column index mapping  will be present for
   * accessing the members from the block.
   *
   * @param dimensionColumnPage
   * @param numberOfRows
   * @return BitSet.
   */
  private BitSet setFilteredIndexToBitSetWithColumnIndex(
      DimensionColumnPage dimensionColumnPage, int numberOfRows) {
    BitSet bitSet = new BitSet(numberOfRows);
    int start = 0;
    int startIndex = 0;
    int startMin = 0;
    int endMax = 0;
    byte[][] filterValues = this.filterRangesValues;

    // For Range expression we expect two values. The First is the Min Value and Second is the
    // Max value.
    // Get the Min Value
    if (!startBlockMinIsDefaultStart) {
      start = CarbonUtil
          .getFirstIndexUsingBinarySearch(dimensionColumnPage, startIndex, numberOfRows - 1,
              filterValues[0], greaterThanExp);
      if (greaterThanExp && start >= 0) {
        start = CarbonUtil
            .nextGreaterValueToTarget(start, dimensionColumnPage, filterValues[0],
                numberOfRows);
      }

      if (start < 0) {
        start = -(start + 1);
        if (start == numberOfRows) {
          start = start - 1;
        }
        // Method will compare the tentative index value after binary search, this tentative
        // index needs to be compared by the filter member if its >= filter then from that
        // index the bitset will be considered for filtering process.
        if ((ByteUtil.compare(filterValues[0], dimensionColumnPage
            .getChunkData(dimensionColumnPage.getInvertedIndex(start)))) > 0) {
          start = start + 1;
        }
      }

      startMin = start;
    } else {
      startMin = startIndex;
    }

    // Get the Max value
    if (!endBlockMaxisDefaultEnd) {
      start = CarbonUtil
          .getFirstIndexUsingBinarySearch(dimensionColumnPage, startIndex, numberOfRows - 1,
              filterValues[1], lessThanEqualExp);

      if (lessThanExp && start >= 0) {
        start =
            CarbonUtil.nextLesserValueToTarget(start, dimensionColumnPage, filterValues[1]);
      }

      if (start < 0) {
        start = -(start + 1);
        if (start == numberOfRows) {
          start = start - 1;
        }
        // In case the start is less than 0, then positive value of start is pointing to the next
        // value of the searched key. So move to the previous one.
        if ((ByteUtil.compare(filterValues[1],
            dimensionColumnPage.getChunkData(dimensionColumnPage.getInvertedIndex(start)))
            < 0)) {
          start = start - 1;
        }
      }
      endMax = start;
    } else {
      endMax = numberOfRows - 1;
    }

    for (int j = startMin; j <= endMax; j++) {
      bitSet.set(dimensionColumnPage.getInvertedIndex(j));
    }

    // Binary Search cannot be done on '@NU#LL$!", so need to check and compare for null on
    // matching row.
    if (dimensionColumnPage.isNoDictionaryColumn() && !dimensionColumnPage.isAdaptiveEncoded()) {
      updateForNoDictionaryColumn(startMin, endMax, dimensionColumnPage, bitSet);
    }
    return bitSet;
  }

  private void updateForNoDictionaryColumn(int start, int end, DimensionColumnPage dataChunk,
      BitSet bitset) {
    for (int j = start; j <= end; j++) {
      if (dataChunk.compareTo(j, CarbonCommonConstants.MEMBER_DEFAULT_VAL_ARRAY) == 0
          || dataChunk.compareTo(j, CarbonCommonConstants.EMPTY_BYTE_ARRAY) == 0) {
        bitset.flip(j);
      }
    }
  }

  /**
   * Method will scan the block and finds the range start index from which all
   * members will be considered for applying range filters. this method will
   * be called if the column is sorted default so column index
   * mapping will be present for accessing the members from the block.
   *
   * @param dimensionColumnPage
   * @param numberOfRows
   * @return BitSet.
   */
  private BitSet setFilteredIndexToBitSet(DimensionColumnPage dimensionColumnPage,
      int numberOfRows) {
    BitSet bitSet = new BitSet(numberOfRows);
    // if (dimensionColumnPage instanceof FixedLengthDimensionColumnPage) {
    byte[][] filterValues = this.filterRangesValues;
    if (dimensionColumnPage.isExplicitSorted()) {
      int start = 0;
      int startMin = 0;
      int endMax = 0;
      int startIndex = 0;
      // For Range expression we expect two values. The First is the Min Value and Second is the
      // Max value.
      if (!startBlockMinIsDefaultStart) {

        start = CarbonUtil
            .getFirstIndexUsingBinarySearch(dimensionColumnPage, startIndex, numberOfRows - 1,
                filterValues[0], greaterThanExp);

        if (greaterThanExp && start >= 0) {
          start = CarbonUtil
              .nextGreaterValueToTarget(start, dimensionColumnPage, filterValues[0],
                  numberOfRows);
        }

        if (start < 0) {
          start = -(start + 1);
          if (start == numberOfRows) {
            start = start - 1;
          }
          // Method will compare the tentative index value after binary search, this tentative
          // index needs to be compared by the filter member if its >= filter then from that
          // index the bitset will be considered for filtering process.
          if ((ByteUtil.compare(filterValues[0], dimensionColumnPage.getChunkData(start)))
              > 0) {
            start = start + 1;
          }
        }
        startMin = start;
      } else {
        startMin = startIndex;
      }

      if (!endBlockMaxisDefaultEnd) {
        start = CarbonUtil
            .getFirstIndexUsingBinarySearch(dimensionColumnPage, startIndex, numberOfRows - 1,
                filterValues[1], lessThanEqualExp);

        if (lessThanExp && start >= 0) {
          start =
              CarbonUtil.nextLesserValueToTarget(start, dimensionColumnPage, filterValues[1]);
        }

        if (start < 0) {
          start = -(start + 1);
          if (start == numberOfRows) {
            start = start - 1;
          }
          // In case the start is less than 0, then positive value of start is pointing to the next
          // value of the searched key. So move to the previous one.
          if ((ByteUtil.compare(filterValues[1], dimensionColumnPage.getChunkData(start))
              < 0)) {
            start = start - 1;
          }
        }
        endMax = start;
      } else {
        endMax = numberOfRows - 1;
      }

      for (int j = startMin; j <= endMax; j++) {
        bitSet.set(j);
      }

      // Binary Search cannot be done on '@NU#LL$!", so need to check and compare for null on
      // matching row.
      if (dimensionColumnPage.isNoDictionaryColumn()) {
        updateForNoDictionaryColumn(startMin, endMax, dimensionColumnPage, bitSet);
      }
    } else {
      byte[] defaultValue = null;
      if (dimColEvaluatorInfo.getDimension().getDataType() == DataTypes.DATE) {
        defaultValue =
            FilterUtil.getDefaultNullValue(dimColEvaluatorInfo.getDimension());
      } else if (dimColEvaluatorInfo.getDimension().getDataType() == DataTypes.STRING) {
        defaultValue = CarbonCommonConstants.MEMBER_DEFAULT_VAL_ARRAY;
      } else if (!dimensionColumnPage.isAdaptiveEncoded()) {
        defaultValue = CarbonCommonConstants.EMPTY_BYTE_ARRAY;
      }

      // evaluate result for lower range value first and then perform and operation in the
      // upper range value in order to compute the final result
      bitSet = evaluateGreaterThanFilterForUnsortedColumn(dimensionColumnPage, filterValues[0],
          numberOfRows);
      BitSet upperRangeBitSet =
          evaluateLessThanFilterForUnsortedColumn(dimensionColumnPage, filterValues[1],
              numberOfRows);
      bitSet.and(upperRangeBitSet);
      FilterUtil.removeNullValues(dimensionColumnPage, bitSet, defaultValue);
    }
    return bitSet;
  }

  /**
   * This method will evaluate the result for filter column based on the lower range value
   *
   * @param dimensionColumnPage
   * @param filterValue
   * @param numberOfRows
   * @return
   */
  private BitSet evaluateGreaterThanFilterForUnsortedColumn(
      DimensionColumnPage dimensionColumnPage, byte[] filterValue, int numberOfRows) {
    BitSet bitSet = new BitSet(numberOfRows);
    if (greaterThanExp) {
      for (int i = 0; i < numberOfRows; i++) {
        if ((ByteUtil.compare(dimensionColumnPage.getChunkData(i), filterValue) > 0)) {
          bitSet.set(i);
        }
      }
    } else if (greaterThanEqualExp) {
      for (int i = 0; i < numberOfRows; i++) {
        if ((ByteUtil.compare(dimensionColumnPage.getChunkData(i), filterValue) >= 0)) {
          bitSet.set(i);
        }
      }
    }
    return bitSet;
  }

  /**
   * This method will evaluate the result for filter column based on the upper range value
   *
   * @param dimensionColumnPage
   * @param filterValue
   * @param numberOfRows
   * @return
   */
  private BitSet evaluateLessThanFilterForUnsortedColumn(
      DimensionColumnPage dimensionColumnPage, byte[] filterValue, int numberOfRows) {
    BitSet bitSet = new BitSet(numberOfRows);
    if (lessThanExp) {
      for (int i = 0; i < numberOfRows; i++) {
        if ((ByteUtil.compare(dimensionColumnPage.getChunkData(i), filterValue) < 0)) {
          bitSet.set(i);
        }
      }
    } else if (lessThanEqualExp) {
      for (int i = 0; i < numberOfRows; i++) {
        if ((ByteUtil.compare(dimensionColumnPage.getChunkData(i), filterValue) <= 0)) {
          bitSet.set(i);
        }
      }
    }
    return bitSet;
  }

  /**
   * Method to read the blocks.
   * @param rawBlockletColumnChunks
   * @throws IOException
   */
  @Override
  public void readColumnChunks(RawBlockletColumnChunks rawBlockletColumnChunks) throws IOException {
    if (isDimensionPresentInCurrentBlock) {
      int chunkIndex = segmentProperties.getDimensionOrdinalToChunkMapping()
          .get(dimColEvaluatorInfo.getColumnIndex());
      if (null == rawBlockletColumnChunks.getDimensionRawColumnChunks()[chunkIndex]) {
        rawBlockletColumnChunks.getDimensionRawColumnChunks()[chunkIndex] =
            rawBlockletColumnChunks.getDataBlock().readDimensionChunk(
                rawBlockletColumnChunks.getFileReader(), chunkIndex);
      }
    }
  }
}
