Пример #1
0
ColumnarResults::ColumnarResults(const std::shared_ptr<RowSetMemoryOwner> row_set_mem_owner,
                                 const ResultSet& rows,
                                 const size_t num_columns,
                                 const std::vector<SQLTypeInfo>& target_types)
    : column_buffers_(num_columns),
      num_rows_(use_parallel_algorithms(rows) ? rows.entryCount() : rows.rowCount()),
      target_types_(target_types) {
  column_buffers_.resize(num_columns);
  for (size_t i = 0; i < num_columns; ++i) {
    const bool is_varlen = target_types[i].is_array() ||
                           (target_types[i].is_string() && target_types[i].get_compression() == kENCODING_NONE);
    if (is_varlen) {
      throw ColumnarConversionNotSupported();
    }
    column_buffers_[i] = reinterpret_cast<const int8_t*>(checked_malloc(num_rows_ * target_types[i].get_size()));
    row_set_mem_owner->addColBuffer(column_buffers_[i]);
  }
  std::atomic<size_t> row_idx{0};
  const auto do_work = [num_columns, &target_types, this](const std::vector<TargetValue>& crt_row,
                                                          const size_t row_idx) {
    for (size_t i = 0; i < num_columns; ++i) {
      const auto col_val = crt_row[i];
      const auto scalar_col_val = boost::get<ScalarTargetValue>(&col_val);
      CHECK(scalar_col_val);
      auto i64_p = boost::get<int64_t>(scalar_col_val);
      const auto& type_info = target_types[i];
      if (i64_p) {
        const auto val = fixed_encoding_nullable_val(*i64_p, type_info);
        switch (target_types[i].get_size()) {
          case 1:
            ((int8_t*)column_buffers_[i])[row_idx] = static_cast<int8_t>(val);
            break;
          case 2:
            ((int16_t*)column_buffers_[i])[row_idx] = static_cast<int16_t>(val);
            break;
          case 4:
            ((int32_t*)column_buffers_[i])[row_idx] = static_cast<int32_t>(val);
            break;
          case 8:
            ((int64_t*)column_buffers_[i])[row_idx] = val;
            break;
          default:
            CHECK(false);
        }
      } else {
        CHECK(target_types[i].is_fp());
        switch (target_types[i].get_type()) {
          case kFLOAT: {
            auto float_p = boost::get<float>(scalar_col_val);
            ((float*)column_buffers_[i])[row_idx] = static_cast<float>(*float_p);
            break;
          }
          case kDOUBLE: {
            auto double_p = boost::get<double>(scalar_col_val);
            ((double*)column_buffers_[i])[row_idx] = static_cast<double>(*double_p);
            break;
          }
          default:
            CHECK(false);
        }
      }
    }
  };
  if (use_parallel_algorithms(rows)) {
    const size_t worker_count = cpu_threads();
    std::vector<std::future<void>> conversion_threads;
    const auto entry_count = rows.entryCount();
    for (size_t i = 0, start_entry = 0, stride = (entry_count + worker_count - 1) / worker_count;
         i < worker_count && start_entry < entry_count;
         ++i, start_entry += stride) {
      const auto end_entry = std::min(start_entry + stride, entry_count);
      conversion_threads.push_back(std::async(std::launch::async,
                                              [&rows, &do_work, &row_idx](const size_t start, const size_t end) {
                                                for (size_t i = start; i < end; ++i) {
                                                  const auto crt_row = rows.getRowAtNoTranslations(i);
                                                  if (!crt_row.empty()) {
                                                    do_work(crt_row, row_idx.fetch_add(1));
                                                  }
                                                }
                                              },
                                              start_entry,
                                              end_entry));
    }
    for (auto& child : conversion_threads) {
      child.wait();
    }
    for (auto& child : conversion_threads) {
      child.get();
    }
    num_rows_ = row_idx;
    rows.setCachedRowCount(num_rows_);
    return;
  }
  while (true) {
    const auto crt_row = rows.getNextRow(false, false);
    if (crt_row.empty()) {
      break;
    }
    do_work(crt_row, row_idx);
    ++row_idx;
  }
  rows.moveToBegin();
}