Example #1
0
BTREE_TEMPLATE_ARGUMENT
void BTREE_TEMPLATE_TYPE::Scan(const std::vector<common::Value *> &value_list,
                               const std::vector<oid_t> &tuple_column_id_list,
                               const std::vector<ExpressionType> &expr_list,
                               const ScanDirectionType &scan_direction,
                               std::vector<ValueType> &result,
                               const ConjunctionScanPredicate *csp_p) {

  // First make sure all three components of the scan predicate are
  // of the same length
  // Since there is a 1-to-1 correspondense between these three vectors
  PL_ASSERT(tuple_column_id_list.size() == expr_list.size());
  PL_ASSERT(tuple_column_id_list.size() == value_list.size());

  // This is a hack - we do not support backward scan
  if (scan_direction == SCAN_DIRECTION_TYPE_INVALID) {
    throw Exception("Invalid scan direction \n");
  }

  LOG_TRACE("Point Query = %d; Full Scan = %d ", csp_p->IsPointQuery(),
            csp_p->IsFullIndexScan());

  index_lock.ReadLock();

  if (csp_p->IsPointQuery() == true) {
    // For point query we construct the key and use equal_range

    const storage::Tuple *point_query_key_p = csp_p->GetPointQueryKey();

    KeyType point_query_key;
    point_query_key.SetFromKey(point_query_key_p);

    // Use equal_range to mark two ends of the scan
    auto scan_itr_pair = container.equal_range(point_query_key);

    auto scan_begin_itr = scan_itr_pair.first;
    auto scan_end_itr = scan_itr_pair.second;

    for (auto scan_itr = scan_begin_itr; scan_itr != scan_end_itr; scan_itr++) {
      auto scan_current_key = scan_itr->first;
      auto tuple =
          scan_current_key.GetTupleForComparison(metadata->GetKeySchema());

      if (Compare(tuple, tuple_column_id_list, expr_list, value_list) == true) {
        result.push_back(scan_itr->second);
      }
    }
  } else if (csp_p->IsFullIndexScan() == true) {
    // If it is a full index scan, then just do the scan

    for (auto scan_itr = container.begin(); scan_itr != container.end();
         scan_itr++) {
      // Unpack the key as a standard tuple for comparison
      auto scan_current_key = scan_itr->first;
      auto tuple =
          scan_current_key.GetTupleForComparison(metadata->GetKeySchema());

      // Compare whether the current key satisfies the predicate
      // since we just narrowed down search range using low key and
      // high key for scan, it is still possible that there are tuples
      // for which the predicate is not true
      if (Compare(tuple, tuple_column_id_list, expr_list, value_list) == true) {
        result.push_back(scan_itr->second);
      }
    }  // for it from begin() to end()
  } else {
    const storage::Tuple *low_key_p = csp_p->GetLowKey();
    const storage::Tuple *high_key_p = csp_p->GetHighKey();

    // Construct low key and high key in KeyType form, rather than
    // the standard in-memory tuple
    KeyType index_low_key;
    KeyType index_high_key;
    index_low_key.SetFromKey(low_key_p);
    index_high_key.SetFromKey(high_key_p);

    // It is good that we have equal_range
    auto scan_begin_itr = container.equal_range(index_low_key).first;
    auto scan_end_itr = container.equal_range(index_high_key).second;

    for (auto scan_itr = scan_begin_itr; scan_itr != scan_end_itr; scan_itr++) {
      auto scan_current_key = scan_itr->first;
      auto tuple =
          scan_current_key.GetTupleForComparison(metadata->GetKeySchema());

      if (Compare(tuple, tuple_column_id_list, expr_list, value_list) == true) {
        result.push_back(scan_itr->second);
      }
    }
  }  // if is full scan

  index_lock.Unlock();

  if (FLAGS_stats_mode != STATS_TYPE_INVALID) {
    stats::BackendStatsContext::GetInstance().IncrementIndexReads(result.size(),
                                                                  metadata);
  }
  return;
}
Example #2
0
std::vector<ItemPointer>
BTreeIndex<KeyType, ValueType, KeyComparator, KeyEqualityChecker>::Scan(
    const std::vector<Value> &values,
    const std::vector<oid_t> &key_column_ids,
    const std::vector<ExpressionType> &expr_types,
    const ScanDirectionType& scan_direction) {
  std::vector<ItemPointer> result;
  KeyType index_key;

  {
    index_lock.ReadLock();

    // Check if we have leading (leftmost) column equality
    // refer : http://www.postgresql.org/docs/8.2/static/indexes-multicolumn.html
    oid_t leading_column_id = 0;
    auto key_column_ids_itr = std::find(
        key_column_ids.begin(), key_column_ids.end(), leading_column_id);

    // SPECIAL CASE : leading column id is one of the key column ids
    // and is involved in a equality constraint
    bool special_case = false;
    if (key_column_ids_itr != key_column_ids.end()) {
      auto offset = std::distance(key_column_ids.begin(), key_column_ids_itr);
      if (expr_types[offset] == EXPRESSION_TYPE_COMPARE_EQUAL) {
        special_case = true;
      }
    }

    LOG_TRACE("Special case : %d ", special_case);

    auto scan_begin_itr = container.begin();
    std::unique_ptr<storage::Tuple> start_key;
    bool all_constraints_are_equal = false;

    // If it is a special case, we can figure out the range to scan in the index
    if (special_case == true) {

      start_key.reset(new storage::Tuple(metadata->GetKeySchema(), true));
      index_key.SetFromKey(start_key.get());

      // Construct the lower bound key tuple
      all_constraints_are_equal =
          ConstructLowerBoundTuple(start_key.get(), values, key_column_ids, expr_types);
      LOG_TRACE("All constraints are equal : %d ", all_constraints_are_equal);

      // Set scan begin iterator
      scan_begin_itr = container.equal_range(index_key).first;
    }

    switch(scan_direction){
      case SCAN_DIRECTION_TYPE_FORWARD:
      case SCAN_DIRECTION_TYPE_BACKWARD: {

        // Scan the index entries in forward direction
        for (auto scan_itr = scan_begin_itr; scan_itr != container.end(); scan_itr++) {
          auto scan_current_key = scan_itr->first;
          auto tuple = scan_current_key.GetTupleForComparison(metadata->GetKeySchema());

          // Compare the current key in the scan with "values" based on "expression types"
          // For instance, "5" EXPR_GREATER_THAN "2" is true
          if (Compare(tuple, key_column_ids, expr_types, values) == true) {
            ItemPointer location = scan_itr->second;
            result.push_back(location);
          }
          else {
            // We can stop scanning if we know that all constraints are equal
            if(all_constraints_are_equal == true) {
              break;
            }
          }
        }

      }
      break;

      case SCAN_DIRECTION_TYPE_INVALID:
      default:
        throw Exception("Invalid scan direction \n");
        break;
    }

    index_lock.Unlock();
  }

  return result;
}