blob: 39d9e589c5f940b7fc29eb0b54fa1e1b0c66373e [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/ConjunctionPredicate.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 ConjunctionPredicate::getProto() const {
serialization::Predicate proto;
proto.set_predicate_type(serialization::Predicate::CONJUNCTION);
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* ConjunctionPredicate::clone() const {
ConjunctionPredicate *clone = new ConjunctionPredicate();
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 ConjunctionPredicate::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 false;
}
}
return true;
}
}
bool ConjunctionPredicate::matchesForJoinedTuples(
const ValueAccessor &left_accessor,
const tuple_id left_tuple_id,
const ValueAccessor &right_accessor,
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_tuple_id,
right_accessor,
right_tuple_id)) {
return false;
}
}
return true;
}
}
TupleIdSequence* ConjunctionPredicate::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 *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);
}
for (PtrList<Predicate>::const_iterator it = dynamic_operand_list_.begin();
it != dynamic_operand_list_.end();
++it) {
if (current_filter->empty()) {
break;
}
std::unique_ptr<TupleIdSequence> operand_result(it->getAllMatches(accessor,
sub_blocks_ref,
current_filter,
existence_map));
current_filter->intersectWith(*operand_result);
}
return current_filter;
}
}
void ConjunctionPredicate::addPredicate(Predicate *operand) {
if (operand->getPredicateType() == kConjunction) {
ConjunctionPredicate *conjunction_operand = static_cast<ConjunctionPredicate*>(operand);
PtrList<Predicate>::iterator checkpos;
if (static_operand_list_.empty()) {
static_operand_list_.splice(static_operand_list_.end(), conjunction_operand->static_operand_list_);
checkpos = static_operand_list_.begin();
} else {
checkpos = static_operand_list_.end();
--checkpos;
static_operand_list_.splice(static_operand_list_.end(), conjunction_operand->static_operand_list_);
++checkpos;
}
while (checkpos != static_operand_list_.end()) {
processStaticOperand(*checkpos);
++checkpos;
}
if (!conjunction_operand->dynamic_operand_list_.empty()) {
dynamic_operand_list_.splice(dynamic_operand_list_.end(), conjunction_operand->dynamic_operand_list_);
processDynamicOperand();
}
delete conjunction_operand;
} else {
if (operand->hasStaticResult()) {
static_operand_list_.push_back(operand);
processStaticOperand(*operand);
} else {
dynamic_operand_list_.push_back(operand);
processDynamicOperand();
}
}
}
void ConjunctionPredicate::processStaticOperand(const Predicate &operand) {
if (!operand.getStaticResult()) {
has_static_result_ = true;
static_result_ = false;
}
}
void ConjunctionPredicate::processDynamicOperand() {
if (has_static_result_) {
if (static_result_) {
has_static_result_ = false;
}
}
}
} // namespace quickstep