blob: e117c99520a190c8525b466b898c403b9f82a9a7 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
**/
#include "expressions/predicate/DisjunctionPredicate.hpp"
#include <memory>
#include "expressions/Expressions.pb.h"
#include "expressions/predicate/Predicate.hpp"
#include "storage/TupleIdSequence.hpp"
#include "storage/ValueAccessor.hpp"
#include "utility/PtrList.hpp"
namespace quickstep {
serialization::Predicate DisjunctionPredicate::getProto() const {
serialization::Predicate proto;
proto.set_predicate_type(serialization::Predicate::DISJUNCTION);
for (PtrList<Predicate>::const_iterator it(static_operand_list_.begin());
it != static_operand_list_.end();
++it) {
proto.AddExtension(serialization::PredicateWithList::operands)->CopyFrom(it->getProto());
}
for (PtrList<Predicate>::const_iterator it(dynamic_operand_list_.begin());
it != dynamic_operand_list_.end();
++it) {
proto.AddExtension(serialization::PredicateWithList::operands)->CopyFrom(it->getProto());
}
return proto;
}
Predicate* DisjunctionPredicate::clone() const {
DisjunctionPredicate *clone = new DisjunctionPredicate();
for (PtrList<Predicate>::const_iterator it = static_operand_list_.begin();
it != static_operand_list_.end();
++it) {
clone->addPredicate(it->clone());
}
for (PtrList<Predicate>::const_iterator it = dynamic_operand_list_.begin();
it != dynamic_operand_list_.end();
++it) {
clone->addPredicate(it->clone());
}
return clone;
}
bool DisjunctionPredicate::matchesForSingleTuple(const ValueAccessor &accessor,
const tuple_id tuple) const {
if (has_static_result_) {
return static_result_;
} else {
for (PtrList<Predicate>::const_iterator it = dynamic_operand_list_.begin();
it != dynamic_operand_list_.end();
++it) {
if (it->matchesForSingleTuple(accessor, tuple)) {
return true;
}
}
return false;
}
}
bool DisjunctionPredicate::matchesForJoinedTuples(
const ValueAccessor &left_accessor,
const relation_id left_relation_id,
const tuple_id left_tuple_id,
const ValueAccessor &right_accessor,
const relation_id right_relation_id,
const tuple_id right_tuple_id) const {
if (has_static_result_) {
return static_result_;
} else {
for (PtrList<Predicate>::const_iterator it = dynamic_operand_list_.begin();
it != dynamic_operand_list_.end();
++it) {
if (it->matchesForJoinedTuples(left_accessor,
left_relation_id,
left_tuple_id,
right_accessor,
right_relation_id,
right_tuple_id)) {
return true;
}
}
return false;
}
}
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;
}
}
void DisjunctionPredicate::addPredicate(Predicate *operand) {
if (operand->getPredicateType() == kDisjunction) {
DisjunctionPredicate *disjunction_operand = static_cast<DisjunctionPredicate*>(operand);
PtrList<Predicate>::iterator checkpos;
if (static_operand_list_.empty()) {
static_operand_list_.splice(static_operand_list_.end(), disjunction_operand->static_operand_list_);
checkpos = static_operand_list_.begin();
} else {
checkpos = static_operand_list_.end();
--checkpos;
static_operand_list_.splice(static_operand_list_.end(), disjunction_operand->static_operand_list_);
++checkpos;
}
while (checkpos != static_operand_list_.end()) {
processStaticOperand(*checkpos);
++checkpos;
}
if (!disjunction_operand->dynamic_operand_list_.empty()) {
dynamic_operand_list_.splice(dynamic_operand_list_.end(), disjunction_operand->dynamic_operand_list_);
processDynamicOperand();
}
delete disjunction_operand;
} else {
if (operand->hasStaticResult()) {
static_operand_list_.push_back(operand);
processStaticOperand(*operand);
} else {
dynamic_operand_list_.push_back(operand);
processDynamicOperand();
}
}
}
void DisjunctionPredicate::processStaticOperand(const Predicate &operand) {
if (operand.getStaticResult()) {
has_static_result_ = true;
static_result_ = true;
} else if (fresh_) {
has_static_result_ = true;
static_result_ = false;
}
fresh_ = false;
}
void DisjunctionPredicate::processDynamicOperand() {
if (has_static_result_ && !static_result_) {
has_static_result_ = false;
} else if (fresh_) {
has_static_result_ = false;
}
fresh_ = false;
}
} // namespace quickstep