TupleIdSequence* TupleStorageSubBlock::getMatchesForPredicate(const Predicate *pred) const { TupleIdSequence *matches = new TupleIdSequence(); tuple_id max_tid = getMaxTupleID(); if (pred == NULL) { if (isPacked()) { for (tuple_id tid = 0; tid <= max_tid; ++tid) { matches->append(tid); } } else { for (tuple_id tid = 0; tid <= max_tid; ++tid) { if (hasTupleWithID(tid)) { matches->append(tid); } } } } else { if (isPacked()) { for (tuple_id tid = 0; tid <= max_tid; ++tid) { if (pred->matchesForSingleTuple(*this, tid)) { matches->append(tid); } } } else { for (tuple_id tid = 0; tid <= max_tid; ++tid) { if (hasTupleWithID(tid) && (pred->matchesForSingleTuple(*this, tid))) { matches->append(tid); } } } } return matches; }
TupleIdSequence* CompressedPackedRowStoreTupleStorageSubBlock::getCodesInRange( const attribute_id attr_id, const std::pair<std::uint32_t, std::uint32_t> range) const { TupleIdSequence *matches = new TupleIdSequence(); const char *attr_location = static_cast<const char*>(tuple_storage_) + attribute_offsets_[attr_id]; switch (compression_info_.attribute_size(attr_id)) { case 1: for (tuple_id tid = 0; tid < *static_cast<const tuple_id*>(sub_block_memory_); ++tid, attr_location += tuple_length_bytes_) { if (range.first <= (*reinterpret_cast<const uint8_t*>(attr_location)) && (*reinterpret_cast<const uint8_t*>(attr_location) < range.second)) { matches->append(tid); } } break; case 2: for (tuple_id tid = 0; tid < *static_cast<const tuple_id*>(sub_block_memory_); ++tid, attr_location += tuple_length_bytes_) { if (range.first <= (*reinterpret_cast<const uint16_t*>(attr_location)) && (*reinterpret_cast<const uint16_t*>(attr_location) < range.second)) { matches->append(tid); } } break; case 4: for (tuple_id tid = 0; tid < *static_cast<const tuple_id*>(sub_block_memory_); ++tid, attr_location += tuple_length_bytes_) { if (range.first <= (*reinterpret_cast<const uint32_t*>(attr_location)) && (*reinterpret_cast<const uint32_t*>(attr_location) < range.second)) { matches->append(tid); } } break; default: FATAL_ERROR("Unexpected byte-length (not 1, 2, or 4) for compressed " "attribute ID " << attr_id << " in CompressedPackedRowStoreTupleStorageSubBlock::getCodesInRange()"); } return matches; }
TupleIdSequence* SortColumnPredicateEvaluator::EvaluatePredicateForUncompressedSortColumn( const Predicate &predicate, const CatalogRelation &relation, const attribute_id sort_attribute_id, void *sort_attribute_stripe, const tuple_id num_tuples) { // Determine if the predicate is a comparison of the sort column with a literal. if (predicate.isAttributeLiteralComparisonPredicate()) { const ComparisonPredicate &comparison_predicate = static_cast<const ComparisonPredicate&>(predicate); const CatalogAttribute *comparison_attribute = NULL; bool left_literal = false; if (comparison_predicate.getLeftOperand().hasStaticValue()) { DEBUG_ASSERT(comparison_predicate.getRightOperand().getDataSource() == Scalar::kAttribute); comparison_attribute = &(static_cast<const ScalarAttribute&>(comparison_predicate.getRightOperand()).getAttribute()); left_literal = true; } else { DEBUG_ASSERT(comparison_predicate.getLeftOperand().getDataSource() == Scalar::kAttribute); comparison_attribute = &(static_cast<const ScalarAttribute&>(comparison_predicate.getLeftOperand()).getAttribute()); left_literal = false; } DEBUG_ASSERT(comparison_attribute->getParent().getID() == relation.getID()); if (comparison_attribute->getID() == sort_attribute_id) { const LiteralTypeInstance* comparison_literal; if (left_literal) { comparison_literal = &(comparison_predicate.getLeftOperand().getStaticValue()); } else { comparison_literal = &(comparison_predicate.getRightOperand().getStaticValue()); } // NOTE(chasseur): A standards-compliant implementation of lower_bound // always compares the iterator on the left with the literal on the right, // while upper_bound compares the literal on the left with the iterator // on the right. These will work even if comparison_attribute and // comparison_literal are different types. const Comparison &less_comparison = Comparison::GetComparison(Comparison::kLess); ScopedPtr<UncheckedComparator> fast_comparator_lower( less_comparison.makeUncheckedComparatorForTypes(comparison_attribute->getType(), comparison_literal->getType())); STLUncheckedComparatorWrapper comp_lower(*fast_comparator_lower); ScopedPtr<UncheckedComparator> fast_comparator_upper( less_comparison.makeUncheckedComparatorForTypes(comparison_literal->getType(), comparison_attribute->getType())); STLUncheckedComparatorWrapper comp_upper(*fast_comparator_upper); // Find the bounds on the range of matching tuples. tuple_id min_match = 0; tuple_id max_match_bound = num_tuples; ColumnStripeIterator begin_it(sort_attribute_stripe, relation.getAttributeById(sort_attribute_id).getType().maximumByteLength(), 0); ColumnStripeIterator end_it(sort_attribute_stripe, relation.getAttributeById(sort_attribute_id).getType().maximumByteLength(), num_tuples); switch (comparison_predicate.getComparison().getComparisonID()) { case Comparison::kEqual: // Note: There is a special branch below for kNotEqual which takes the // complement of the matched range. case Comparison::kNotEqual: min_match = lower_bound(begin_it, end_it, comparison_literal->getDataPtr(), comp_lower).getTuplePosition(); max_match_bound = upper_bound(begin_it, end_it, comparison_literal->getDataPtr(), comp_upper).getTuplePosition(); break; case Comparison::kLess: if (left_literal) { min_match = upper_bound(begin_it, end_it, comparison_literal->getDataPtr(), comp_upper).getTuplePosition(); } else { max_match_bound = lower_bound(begin_it, end_it, comparison_literal->getDataPtr(), comp_lower).getTuplePosition(); } break; case Comparison::kLessOrEqual: if (left_literal) { min_match = lower_bound(begin_it, end_it, comparison_literal->getDataPtr(), comp_lower).getTuplePosition(); } else { max_match_bound = upper_bound(begin_it, end_it, comparison_literal->getDataPtr(), comp_upper).getTuplePosition(); } break; case Comparison::kGreater: if (left_literal) { max_match_bound = lower_bound(begin_it, end_it, comparison_literal->getDataPtr(), comp_lower).getTuplePosition(); } else { min_match = upper_bound(begin_it, end_it, comparison_literal->getDataPtr(), comp_upper).getTuplePosition(); } break; case Comparison::kGreaterOrEqual: if (left_literal) { max_match_bound = upper_bound(begin_it, end_it, comparison_literal->getDataPtr(), comp_upper).getTuplePosition(); } else { min_match = lower_bound(begin_it, end_it, comparison_literal->getDataPtr(), comp_lower).getTuplePosition(); } break; default: FATAL_ERROR("Unknown Comparison in SortColumnPredicateEvaluator::" "EvaluatePredicateForUncompressedSortColumn()"); } // Create and return the sequence of matches. TupleIdSequence *matches = new TupleIdSequence(); if (comparison_predicate.getComparison().getComparisonID() == Comparison::kNotEqual) { // Special case: return all tuples NOT in the range for kEqual. for (tuple_id tid = 0; tid < min_match; ++tid) { matches->append(tid); } for (tuple_id tid = max_match_bound; tid < num_tuples; ++tid) { matches->append(tid); } } else { for (tuple_id tid = min_match; tid < max_match_bound; ++tid) { matches->append(tid); } } return matches; } else { return NULL; } } else { // Can not evaluate a non-comparison predicate, so pass through. return NULL; } }