// ObSeqSSTableScanner stored pointer of ObScanParam but not param's value
    // this usage maybe a problem when user free %param before call next_cell
    // TODO: ObSeqSSTableScanner need store %param for itself.
    int ObSeqSSTableScanner::set_scan_param(
        const common::ObScanParam& param, 
        ObBlockCache& block_cache, 
        ObBlockIndexCache& block_index_cache,
        bool not_exit_col_ret_nop)
    {
      int ret = OB_SUCCESS;

      if (NULL == param.get_range() || param.get_range()->empty())
      {
        TBSYS_LOG(ERROR, "input scan param range is empty, cannot scan.");
        ret = OB_INVALID_ARGUMENT;
      }
      else
      {
        if (TBSYS_LOGGER._level >= TBSYS_LOG_LEVEL_DEBUG)
        {
          char range_buf[OB_RANGE_STR_BUFSIZ];
          param.get_range()->to_string(range_buf, OB_RANGE_STR_BUFSIZ);
          TBSYS_LOG(DEBUG, "scan input param range, range=%s", range_buf);
        }

        block_cache_ = &block_cache;
        block_index_cache_ = &block_index_cache;
        scan_param_ = &param; 
        cur_iter_idx_ = 0;
        cur_iter_status_ = NOT_START;
        sstable_array_.clear();
        not_exit_col_ret_nop_ = not_exit_col_ret_nop;
      }

      return ret;
    }
int TaskFactory::add_columns_conf(const uint64_t table_id, common::ObScanParam & param, const TableConf *conf)
{
  int ret = OB_SUCCESS;
  TableConf::ColumnIterator itr = conf->column_begin();

  ObString column;
  while (itr != conf->column_end())
  {
    const char *column_name = *itr;
    if (conf->is_null_column(column_name) || conf->is_rowkey(column_name))
    {
      itr++;
      continue;
    }

    TBSYS_LOG(DEBUG, "columns with conf, column = %s", column_name);
    column.assign(const_cast<char *>(*itr), (int32_t)strlen(column_name));
    ret = param.add_column(column);
    if (ret != OB_SUCCESS)
    {
      TBSYS_LOG(ERROR, "add column failed:table[%lu], column[%s], ret[%d]",
                table_id, column_name, ret);
      ret = OB_ERROR;
      break;
    }

    itr++;
  }

  return ret;
}
    int ObChunkServerMergerProxy::cs_scan(const common::ObScanParam & scan_param, 
                                          mergeserver::ObMergerTabletLocation & addr, 
                                          common::ObScanner & scanner, 
                                          common::ObIterator * &it_out)
    {
      int ret = OB_SUCCESS;
      
      ObCellInfo cell_ext;
      UNUSED(addr);
      it_out = NULL;
      cell_array_.clear();

      if ((ret = cs_reader_.scan(scan_param)) != OB_SUCCESS)
      {
        TBSYS_LOG(DEBUG,"scan chunkserver failed");
      }
      else
      {
        it_out = &cs_reader_;
      }

      if (OB_SUCCESS == ret)
      {
        cell_ext.column_id_ = 2; //meaninglessness,just to suppress the scanner warn log

        cell_ext.table_id_ = scan_param.get_table_id();
        cell_ext.row_key_ = scan_param.get_range()->end_key_;

        scanner.clear();
        scanner.set_range(*scan_param.get_range());
        //data version
        scanner.set_data_version(scan_param.get_version_range().start_version_);
        scanner.set_is_req_fullfilled(true,1);

        if ( (ret = scanner.add_cell(cell_ext)) != OB_SUCCESS)
        {
          TBSYS_LOG(DEBUG,"add cell failed(%d)",ret);
        }
      }
      TBSYS_LOG(DEBUG," merger proxy ret [%d]",ret);
      return ret;
    }