TupleIdSequence* DisjunctionPredicate::getAllMatches( ValueAccessor *accessor, // const SubBlocksReference *sub_blocks_ref, const TupleIdSequence *filter, const TupleIdSequence *existence_map) const { if (has_static_result_) { return GenerateSequenceForStaticResult(accessor, filter, existence_map, static_result_); } else { tuple_id end_pos = accessor->getEndPositionVirtual(); TupleIdSequence *union_result = new TupleIdSequence(end_pos); #ifdef QUICKSTEP_ENABLE_VECTOR_PREDICATE_SHORT_CIRCUIT std::unique_ptr<TupleIdSequence> current_filter(new TupleIdSequence(end_pos)); if (filter != nullptr) { current_filter->assignFrom(*filter); } else if (existence_map != nullptr) { current_filter->assignFrom(*existence_map); } else { current_filter->setRange(0, end_pos, true); } #endif // QUICKSTEP_ENABLE_VECTOR_PREDICATE_SHORT_CIRCUIT for (PtrList<Predicate>::const_iterator it = dynamic_operand_list_.begin(); it != dynamic_operand_list_.end(); ++it) { #ifdef QUICKSTEP_ENABLE_VECTOR_PREDICATE_SHORT_CIRCUIT std::unique_ptr<TupleIdSequence> operand_result(it->getAllMatches(accessor, // sub_blocks_ref, current_filter.get(), existence_map)); #else std::unique_ptr<TupleIdSequence> operand_result(it->getAllMatches(accessor, // sub_blocks_ref, filter, existence_map)); #endif // QUICKSTEP_ENABLE_VECTOR_PREDICATE_SHORT_CIRCUIT union_result->unionWith(*operand_result); #ifdef QUICKSTEP_ENABLE_VECTOR_PREDICATE_SHORT_CIRCUIT // Don't bother checking tuples which are already known to match some // part of the union. operand_result->invert(); current_filter->intersectWith(*operand_result); #endif // QUICKSTEP_ENABLE_VECTOR_PREDICATE_SHORT_CIRCUIT } return union_result; } }
TupleIdSequence* ComparisonPredicate::getAllMatches( ValueAccessor *accessor, const SubBlocksReference *sub_blocks_ref, const TupleIdSequence *filter, const TupleIdSequence *existence_map) const { #ifdef QUICKSTEP_ENABLE_VECTOR_PREDICATE_SHORT_CIRCUIT static constexpr bool short_circuit = true; #else static constexpr bool short_circuit = false; #endif if (fast_comparator_.get() == nullptr) { return GenerateSequenceForStaticResult(accessor, filter, existence_map, static_result_); } else if (sub_blocks_ref != nullptr) { // Try to find a method faster than a simple scan to evaluate this // comparison. std::size_t fastest_subblock = std::numeric_limits<std::size_t>::max(); predicate_cost_t lowest_cost = sub_blocks_ref->tuple_store.estimatePredicateEvaluationCost(*this); for (std::size_t index_id = 0; index_id < sub_blocks_ref->indices.size(); ++index_id) { if (sub_blocks_ref->indices_consistent[index_id]) { const predicate_cost_t index_cost = sub_blocks_ref->indices[index_id].estimatePredicateEvaluationCost(*this); if (index_cost < lowest_cost) { fastest_subblock = index_id; lowest_cost = index_cost; } } } if (fastest_subblock != std::numeric_limits<std::size_t>::max()) { return sub_blocks_ref->indices[fastest_subblock].getMatchesForPredicate(*this, filter); } else if (!PredicateCostIsSimpleScan(lowest_cost)) { return sub_blocks_ref->tuple_store.getMatchesForPredicate(*this, filter); } } // When short-circuiting is turned on, we should only evaluate the comparison // for tuples that are set in '*filter'. We might need to generate a // ColumnVector of values for the operand on either side of the comparison // with a call to Scalar::getAllValues() before we evaluate the comparison, // but we only actually care about the operand's values for the tuples that // are set in '*filter' (evaluating the Scalar's value for other tuples would // be a waste of memory and computation). Therefore, we set up a // ValueAccessor here that only iterates over the tuples in '*filter', and we // pass it in to Scalar::getAllValues() calls below so that we only generate // those values that we actually need to check. We use '*filter' in place of // the existence bitmap in such cases, because the filter effectively IS the // existence bitmap for '*short_circuit_adapter' (this way, the tuple IDs // don't get screwed up and still correspond to the original "physical" IDs // in the block). std::unique_ptr<ValueAccessor> short_circuit_adapter; if (short_circuit && (filter != nullptr)) { short_circuit_adapter.reset(accessor->createSharedTupleIdSequenceAdapterVirtual(*filter)); } // NOTE(chasseur): We don't check if both operations have a static value, // because if they did then this comparison would have a static result // which is handled above. if (left_operand_->hasStaticValue()) { #ifdef QUICKSTEP_ENABLE_VECTOR_COPY_ELISION_SELECTION const attribute_id right_operand_attr_id = right_operand_->getAttributeIdForValueAccessor(); if (right_operand_attr_id != -1) { return fast_comparator_->compareStaticValueAndValueAccessor( left_operand_->getStaticValue(), accessor, right_operand_attr_id, filter); } #endif // QUICKSTEP_ENABLE_VECTOR_COPY_ELISION_SELECTION if (short_circuit_adapter) { std::unique_ptr<ColumnVector> right_values(right_operand_->getAllValues( short_circuit_adapter.get(), sub_blocks_ref)); return fast_comparator_->compareStaticValueAndColumnVector( left_operand_->getStaticValue(), *right_values, nullptr, filter); } else { std::unique_ptr<ColumnVector> right_values(right_operand_->getAllValues( accessor, sub_blocks_ref)); return fast_comparator_->compareStaticValueAndColumnVector( left_operand_->getStaticValue(), *right_values, filter, existence_map); } } else if (right_operand_->hasStaticValue()) { #ifdef QUICKSTEP_ENABLE_VECTOR_COPY_ELISION_SELECTION const attribute_id left_operand_attr_id = left_operand_->getAttributeIdForValueAccessor(); if (left_operand_attr_id != -1) { return fast_comparator_->compareValueAccessorAndStaticValue( accessor, left_operand_attr_id, right_operand_->getStaticValue(), filter); } #endif // QUICKSTEP_ENABLE_VECTOR_COPY_ELISION_SELECTION if (short_circuit_adapter) { std::unique_ptr<ColumnVector> left_values(left_operand_->getAllValues( short_circuit_adapter.get(), sub_blocks_ref)); return fast_comparator_->compareColumnVectorAndStaticValue( *left_values, right_operand_->getStaticValue(), nullptr, filter); } else { std::unique_ptr<ColumnVector> left_values(left_operand_->getAllValues( accessor, sub_blocks_ref)); return fast_comparator_->compareColumnVectorAndStaticValue( *left_values, right_operand_->getStaticValue(), filter, existence_map); } } else { #ifdef QUICKSTEP_ENABLE_VECTOR_COPY_ELISION_SELECTION const attribute_id left_operand_attr_id = left_operand_->getAttributeIdForValueAccessor(); const attribute_id right_operand_attr_id = right_operand_->getAttributeIdForValueAccessor(); if (left_operand_attr_id != -1) { if (right_operand_attr_id != -1) { return fast_comparator_->compareSingleValueAccessor(accessor, left_operand_attr_id, right_operand_attr_id, filter); } else { if (short_circuit_adapter) { std::unique_ptr<ColumnVector> right_values(right_operand_->getAllValues( short_circuit_adapter.get(), sub_blocks_ref)); return fast_comparator_->compareValueAccessorAndColumnVector( short_circuit_adapter.get(), left_operand_attr_id, *right_values, nullptr, filter); } else { std::unique_ptr<ColumnVector> right_values(right_operand_->getAllValues( accessor, sub_blocks_ref)); return fast_comparator_->compareValueAccessorAndColumnVector(accessor, left_operand_attr_id, *right_values, filter, existence_map); } } } else if (right_operand_attr_id != -1) { if (short_circuit_adapter) { std::unique_ptr<ColumnVector> left_values(left_operand_->getAllValues( short_circuit_adapter.get(), sub_blocks_ref)); return fast_comparator_->compareColumnVectorAndValueAccessor( *left_values, short_circuit_adapter.get(), right_operand_attr_id, nullptr, filter); } else { std::unique_ptr<ColumnVector> left_values(left_operand_->getAllValues( accessor, sub_blocks_ref)); return fast_comparator_->compareColumnVectorAndValueAccessor(*left_values, accessor, right_operand_attr_id, filter, existence_map); } } #endif // QUICKSTEP_ENABLE_VECTOR_COPY_ELISION_SELECTION if (short_circuit_adapter) { std::unique_ptr<ColumnVector> left_values(left_operand_->getAllValues( short_circuit_adapter.get(), sub_blocks_ref)); std::unique_ptr<ColumnVector> right_values(right_operand_->getAllValues( short_circuit_adapter.get(), sub_blocks_ref)); return fast_comparator_->compareColumnVectors(*left_values, *right_values, nullptr, filter); } else { std::unique_ptr<ColumnVector> left_values(left_operand_->getAllValues( accessor, sub_blocks_ref)); std::unique_ptr<ColumnVector> right_values(right_operand_->getAllValues( accessor, sub_blocks_ref)); return fast_comparator_->compareColumnVectors(*left_values, *right_values, filter, existence_map); } } }
TupleIdSequence* getAllMatches(ValueAccessor *accessor, const SubBlocksReference *sub_blocks_ref, const TupleIdSequence *filter, const TupleIdSequence *existence_map) const override { return GenerateSequenceForStaticResult(accessor, filter, existence_map, true); }