Skip to content

Commit

Permalink
Refactor and clean up Exception.h (#872)
Browse files Browse the repository at this point in the history
Reduce the old code to what is actually used in QLever currently. We now have the following macros:

AD_CONTRACT_CHECK: failure indicates that the function was called with arguments that violate the contract of the function
AD_CORRECTNESS_CHECK: failure indicates that this or an associated function was not implemented correctly
AD_FAIL: fails if code that should be unreachable is reached
AD_THROW: generic macro for throwing an exception including file name and line number
  • Loading branch information
joka921 committed Jan 30, 2023
1 parent 8d61220 commit 0f62bd8
Show file tree
Hide file tree
Showing 115 changed files with 2,218 additions and 2,570 deletions.
2 changes: 1 addition & 1 deletion src/engine/CallFixedSize.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ namespace detail {
// the `array` is `<= maxValue`.
template <int maxValue, size_t NumValues, std::integral Int>
auto callLambdaForIntArray(std::array<Int, NumValues> array, auto&& lambda, auto&&... args) {
AD_CHECK(std::ranges::all_of(array, [](auto el) { return el <= maxValue; }));
AD_CONTRACT_CHECK(std::ranges::all_of(array, [](auto el) { return el <= maxValue; }));
using ArrayType = std::array<Int, NumValues>;

// Call the `lambda` when the correct compile-time `Int`s are given as a
Expand Down
12 changes: 5 additions & 7 deletions src/engine/Engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ class Engine {
template <typename Comp, int WIDTH>
static void filter(const IdTableView<WIDTH>& v, const Comp& comp,
IdTableStatic<WIDTH>* result) {
AD_CHECK(result);
AD_CHECK(result->size() == 0);
AD_CONTRACT_CHECK(result);
AD_CONTRACT_CHECK(result->size() == 0);
LOG(DEBUG) << "Filtering " << v.size() << " elements.\n";
for (const auto& e : v) {
if (comp(e)) {
Expand All @@ -34,8 +34,8 @@ class Engine {
template <int IN_WIDTH, int FILTER_WIDTH>
static void filter(const IdTable& dynV, size_t fc1, size_t fc2,
const IdTable& dynFilter, IdTable* dynResult) {
AD_CHECK(dynResult);
AD_CHECK(dynResult->size() == 0);
AD_CONTRACT_CHECK(dynResult);
AD_CONTRACT_CHECK(dynResult->size() == 0);
LOG(DEBUG) << "Filtering " << dynV.size()
<< " elements with a filter relation with " << dynFilter.size()
<< "elements\n";
Expand Down Expand Up @@ -151,9 +151,7 @@ class Engine {
const IdTableView<WIDTH> input = dynInput.asStaticView<WIDTH>();
IdTableStatic<WIDTH> result = std::move(*dynResult).toStatic<WIDTH>();
if (input.size() > 0) {
AD_CHECK_LE(keepIndices.size(), input.numColumns());
// TODO<joka921> Should we delete copy operations of the new IDtable as
// well.
AD_CONTRACT_CHECK(keepIndices.size() <= input.numColumns());
result = input.clone();

auto last = std::unique(result.begin(), result.end(),
Expand Down
8 changes: 4 additions & 4 deletions src/engine/Filter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ void Filter::computeFilterImpl(ResultTable* outputResultTable,
[&]<sparqlExpression::SingleExpressionResult T>(T&& singleResult) {
if constexpr (std::is_same_v<T, sparqlExpression::VectorWithMemoryLimit<
sparqlExpression::Bool>>) {
AD_CHECK(singleResult.size() == input.size());
AD_CONTRACT_CHECK(singleResult.size() == input.size());
auto totalSize =
std::accumulate(singleResult.begin(), singleResult.end(), 0ul);
output.reserve(totalSize);
Expand All @@ -99,7 +99,7 @@ void Filter::computeFilterImpl(ResultTable* outputResultTable,
output.push_back(input[i]);
}
}
AD_CHECK_EQ(output.size(), totalSize);
AD_CONTRACT_CHECK(output.size() == totalSize);
} else if constexpr (std::is_same_v<T, ad_utility::SetOfIntervals>) {
auto totalSize = std::accumulate(
singleResult._intervals.begin(), singleResult._intervals.end(),
Expand All @@ -108,10 +108,10 @@ void Filter::computeFilterImpl(ResultTable* outputResultTable,
});
output.reserve(totalSize);
for (auto [beg, end] : singleResult._intervals) {
AD_CHECK(end <= input.size());
AD_CONTRACT_CHECK(end <= input.size());
output.insertAtEnd(input.cbegin() + beg, input.cbegin() + end);
}
AD_CHECK_EQ(output.size(), totalSize);
AD_CONTRACT_CHECK(output.size() == totalSize);
} else {
// Default case for all other types. We currently implicitly convert
// all kinds of results (strings, doubles, ints) to bools inside a
Expand Down
11 changes: 4 additions & 7 deletions src/engine/GroupBy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ void GroupBy::processGroup(
auto visitor = [&]<sparqlExpression::SingleExpressionResult T>(
T&& singleResult) mutable {
constexpr static bool isStrongId = std::is_same_v<T, Id>;
AD_CHECK(sparqlExpression::isConstantResult<T>);
AD_CONTRACT_CHECK(sparqlExpression::isConstantResult<T>);
if constexpr (isStrongId) {
resultEntry = singleResult;
*resultType = qlever::ResultType::KB;
Expand All @@ -180,7 +180,7 @@ void GroupBy::processGroup(
singleResult, *(outTable->_localVocab));
} else {
// This should never happen since aggregates always return constants.
AD_FAIL()
AD_FAIL();
}
};

Expand Down Expand Up @@ -308,10 +308,7 @@ void GroupBy::computeResult(ResultTable* result) {
for (const auto& var : _groupByVariables) {
auto it = subtreeVarCols.find(var);
if (it == subtreeVarCols.end()) {
LOG(WARN) << "Group by variable " << var.name() << " is not groupable."
<< std::endl;
AD_THROW(ad_semsearch::Exception::BAD_QUERY,
"Groupby variable " + var.name() + " is not groupable");
AD_THROW("Groupby variable " + var.name() + " is not groupable");
}

groupByColumns.push_back(it->second);
Expand Down Expand Up @@ -395,7 +392,7 @@ bool GroupBy::computeGroupByForSingleIndexScan(ResultTable* result) {
const auto& var = varAndDistinctness.value().variable_;
auto permutation =
getPermutationForThreeVariableTriple(*_subtree, var, var);
AD_CHECK(permutation.has_value());
AD_CONTRACT_CHECK(permutation.has_value());
result->_idTable(0, 0) = Id::makeFromInt(
getIndex().getImpl().numDistinctCol0(permutation.value()).normal_);
} else {
Expand Down
8 changes: 3 additions & 5 deletions src/engine/HasPredicateScan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ HasPredicateScan::HasPredicateScan(QueryExecutionContext* qec,
SparqlTriple triple)
: Operation{qec} {
// Just pick one direction, they should be equivalent.
AD_CHECK(triple._p._iri == HAS_PREDICATE_PREDICATE);
AD_CONTRACT_CHECK(triple._p._iri == HAS_PREDICATE_PREDICATE);
// TODO(schnelle): Handle ?p ql:has-predicate ?p
_type = [&]() {
if (isVariable(triple._s) && (isVariable(triple._o))) {
Expand Down Expand Up @@ -222,17 +222,15 @@ void HasPredicateScan::computeResult(ResultTable* result) {
case ScanType::FREE_S: {
Id objectId;
if (!getIndex().getId(_object, &objectId)) {
AD_THROW(ad_semsearch::Exception::BAD_INPUT,
"The predicate '" + _object + "' is not in the vocabulary.");
AD_THROW("The predicate '" + _object + "' is not in the vocabulary.");
}
HasPredicateScan::computeFreeS(result, objectId, hasPattern, hasPredicate,
patterns);
} break;
case ScanType::FREE_O: {
Id subjectId;
if (!getIndex().getId(_subject, &subjectId)) {
AD_THROW(ad_semsearch::Exception::BAD_INPUT,
"The subject " + _subject + " is not in the vocabulary.");
AD_THROW("The subject " + _subject + " is not in the vocabulary.");
}
HasPredicateScan::computeFreeO(result, subjectId, hasPattern,
hasPredicate, patterns);
Expand Down
9 changes: 4 additions & 5 deletions src/engine/IndexScan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ size_t IndexScan::getResultWidth() const {
case FULL_INDEX_SCAN_OPS:
return 3;
default:
AD_THROW(ad_semsearch::Exception::CHECK_FAILED, "Should be unreachable.");
AD_FAIL();
}
}

Expand All @@ -136,7 +136,7 @@ vector<size_t> IndexScan::resultSortedOn() const {
case FULL_INDEX_SCAN_OPS:
return {0, 1, 2};
default:
AD_THROW(ad_semsearch::Exception::CHECK_FAILED, "Should be unreachable.");
AD_FAIL();
}
}

Expand Down Expand Up @@ -205,7 +205,7 @@ VariableToColumnMap IndexScan::computeVariableToColumnMap() const {
addPredicate();
return res;
default:
AD_THROW(ad_semsearch::Exception::CHECK_FAILED, "Should be unreachable.");
AD_FAIL();
}
}
// _____________________________________________________________________________
Expand Down Expand Up @@ -494,8 +494,7 @@ void IndexScan::determineMultiplicities() {
_multiplicity = idx.getMultiplicities(Index::Permutation::OPS);
break;
default:
AD_THROW(ad_semsearch::Exception::ASSERT_FAILED,
"Switch reached default block unexpectedly!");
AD_FAIL();
}
}
} else {
Expand Down
13 changes: 6 additions & 7 deletions src/engine/Join.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Join::Join(QueryExecutionContext* qec, std::shared_ptr<QueryExecutionTree> t1,
std::shared_ptr<QueryExecutionTree> t2, size_t t1JoinCol,
size_t t2JoinCol, bool keepJoinColumn)
: Operation(qec) {
AD_CHECK(t1 && t2);
AD_CONTRACT_CHECK(t1 && t2);
// Currently all join algorithms require both inputs to be sorted, so we
// enforce the sorting here.
t1 = QueryExecutionTree::createSortedTree(std::move(t1), {t1JoinCol});
Expand Down Expand Up @@ -127,7 +127,7 @@ void Join::computeResult(ResultTable* result) {

LOG(DEBUG) << "Computing Join result..." << endl;

AD_CHECK(result);
AD_CONTRACT_CHECK(result);

result->_idTable.setNumColumns(leftWidth + rightWidth - 1);
result->_resultTypes.reserve(result->_idTable.numColumns());
Expand Down Expand Up @@ -199,7 +199,7 @@ VariableToColumnMap Join::computeVariableToColumnMap() const {
size_t Join::getResultWidth() const {
size_t res = _left->getResultWidth() + _right->getResultWidth() -
(_keepJoinColumn ? 1 : 2);
AD_CHECK(res > 0);
AD_CONTRACT_CHECK(res > 0);
return res;
}

Expand Down Expand Up @@ -259,7 +259,7 @@ size_t Join::getCostEstimate() {
void Join::computeResultForJoinWithFullScanDummy(ResultTable* result) {
LOG(DEBUG) << "Join by making multiple scans..." << endl;
if (isFullScanDummy(_left)) {
AD_CHECK(!isFullScanDummy(_right))
AD_CONTRACT_CHECK(!isFullScanDummy(_right));
_left->getRootOperation()->updateRuntimeInformationWhenOptimizedOut({});
result->_idTable.setNumColumns(_right->getResultWidth() + 2);
result->_sortedBy = {2 + _rightJoinCol};
Expand All @@ -273,7 +273,7 @@ void Join::computeResultForJoinWithFullScanDummy(ResultTable* result) {
doComputeJoinWithFullScanDummyLeft(nonDummyRes->_idTable,
&result->_idTable);
} else {
AD_CHECK(!isFullScanDummy(_left))
AD_CONTRACT_CHECK(!isFullScanDummy(_left));
_right->getRootOperation()->updateRuntimeInformationWhenOptimizedOut({});
result->_idTable.setNumColumns(_left->getResultWidth() + 2);
result->_sortedBy = {_leftJoinCol};
Expand Down Expand Up @@ -329,8 +329,7 @@ Join::ScanMethodType Join::getScanMethod(
scanMethod = scanLambda(OPS);
break;
default:
AD_THROW(ad_semsearch::Exception::CHECK_FAILED,
"Found non-dummy scan where one was expected.");
AD_THROW("Found non-dummy scan where one was expected.");
}
return scanMethod;
}
Expand Down
6 changes: 3 additions & 3 deletions src/engine/LocalVocab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ LocalVocab LocalVocab::clone() const {
const size_t localVocabSize = this->size();
localVocabClone.indexesToWordsMap_.resize(localVocabSize);
for (const auto& [wordInMap, index] : localVocabClone.wordsToIndexesMap_) {
AD_CHECK(index.get() < localVocabSize);
AD_CONTRACT_CHECK(index.get() < localVocabSize);
localVocabClone.indexesToWordsMap_[index.get()] = std::addressof(wordInMap);
}
// Return the clone.
Expand Down Expand Up @@ -89,8 +89,8 @@ const std::string& LocalVocab::getWord(LocalVocabIndex localVocabIndex) const {
std::shared_ptr<LocalVocab> LocalVocab::mergeLocalVocabsIfOneIsEmpty(
const std::shared_ptr<LocalVocab>& localVocab1,
const std::shared_ptr<LocalVocab>& localVocab2) {
AD_CHECK(localVocab1 != nullptr);
AD_CHECK(localVocab2 != nullptr);
AD_CONTRACT_CHECK(localVocab1 != nullptr);
AD_CONTRACT_CHECK(localVocab2 != nullptr);
bool isLocalVocab1Empty = localVocab1->empty();
bool isLocalVocab2Empty = localVocab2->empty();
if (!isLocalVocab1Empty && !isLocalVocab2Empty) {
Expand Down
10 changes: 5 additions & 5 deletions src/engine/Minus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ Minus::Minus(QueryExecutionContext* qec,
// Check that the invariant (inputs are sorted on the matched columns) holds.
auto l = _left->resultSortedOn();
auto r = _right->resultSortedOn();
AD_CHECK(_matchedColumns.size() <= l.size());
AD_CHECK(_matchedColumns.size() <= r.size());
AD_CONTRACT_CHECK(_matchedColumns.size() <= l.size());
AD_CONTRACT_CHECK(_matchedColumns.size() <= r.size());
for (size_t i = 0; i < _matchedColumns.size(); ++i) {
AD_CHECK(_matchedColumns[i][0] == l[i]);
AD_CHECK(_matchedColumns[i][1] == r[i]);
AD_CONTRACT_CHECK(_matchedColumns[i][0] == l[i]);
AD_CONTRACT_CHECK(_matchedColumns[i][1] == r[i]);
}
}

Expand All @@ -45,7 +45,7 @@ string Minus::getDescriptor() const { return "Minus"; }

// _____________________________________________________________________________
void Minus::computeResult(ResultTable* result) {
AD_CHECK(result);
AD_CONTRACT_CHECK(result);
LOG(DEBUG) << "Minus result computation..." << endl;

result->_sortedBy = resultSortedOn();
Expand Down
8 changes: 4 additions & 4 deletions src/engine/MultiColumnJoin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ MultiColumnJoin::MultiColumnJoin(QueryExecutionContext* qec,
const vector<array<ColumnIndex, 2>>& jcs)
: Operation(qec), _joinColumns(jcs), _multiplicitiesComputed(false) {
// Make sure subtrees are ordered so that identical queries can be identified.
AD_CHECK_GT(jcs.size(), 0);
AD_CONTRACT_CHECK(!jcs.empty());
if (t1->asString() < t2->asString()) {
_left = t1;
_right = t2;
Expand Down Expand Up @@ -72,13 +72,13 @@ string MultiColumnJoin::getDescriptor() const {

// _____________________________________________________________________________
void MultiColumnJoin::computeResult(ResultTable* result) {
AD_CHECK(result);
AD_CONTRACT_CHECK(result);
LOG(DEBUG) << "MultiColumnJoin result computation..." << endl;

result->_sortedBy = resultSortedOn();
result->_idTable.setNumColumns(getResultWidth());

AD_CHECK_GE(result->_idTable.numColumns(), _joinColumns.size());
AD_CONTRACT_CHECK(result->_idTable.numColumns() >= _joinColumns.size());

const auto leftResult = _left->getResult();
const auto rightResult = _right->getResult();
Expand Down Expand Up @@ -147,7 +147,7 @@ VariableToColumnMap MultiColumnJoin::computeVariableToColumnMap() const {
size_t MultiColumnJoin::getResultWidth() const {
size_t res =
_left->getResultWidth() + _right->getResultWidth() - _joinColumns.size();
AD_CHECK(res > 0);
AD_CONTRACT_CHECK(res > 0);
return res;
}

Expand Down
14 changes: 7 additions & 7 deletions src/engine/Operation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ shared_ptr<const ResultTable> Operation::getResult(bool isRoot) {
LOG(DEBUG) << "Computed result of size " << resultNumRows << " x "
<< resultNumCols << std::endl;
return result._resultPointer->_resultTable;
} catch (const ad_semsearch::AbortException& e) {
} catch (const ad_utility::AbortException& e) {
// A child Operation was aborted, do not print the information again.
_runtimeInfo.status_ = RuntimeInformation::Status::failedBecauseChildFailed;
throw;
Expand All @@ -158,21 +158,21 @@ shared_ptr<const ResultTable> Operation::getResult(bool isRoot) {
LOG(ERROR) << "Waited for a result from another thread which then failed"
<< endl;
LOG(DEBUG) << asString();
throw ad_semsearch::AbortException(e);
throw ad_utility::AbortException(e);
} catch (const std::exception& e) {
// We are in the innermost level of the exception, so print
LOG(ERROR) << "Aborted Operation" << endl;
LOG(DEBUG) << asString() << endl;
// Rethrow as QUERY_ABORTED allowing us to print the Operation
// only at innermost failure of a recursive call
throw ad_semsearch::AbortException(e);
throw ad_utility::AbortException(e);
} catch (...) {
// We are in the innermost level of the exception, so print
LOG(ERROR) << "Aborted Operation" << endl;
LOG(DEBUG) << asString() << endl;
// Rethrow as QUERY_ABORTED allowing us to print the Operation
// only at innermost failure of a recursive call
throw ad_semsearch::AbortException(
throw ad_utility::AbortException(
"Unexpected expection that is not a subclass of std::exception");
}
}
Expand All @@ -197,7 +197,7 @@ void Operation::updateRuntimeInformationOnSuccess(
bool wasCached = cacheStatus != ad_utility::CacheStatus::computed;
// If the result was read from the cache, then we need the additional
// runtime info for the correct child information etc.
AD_CHECK(!wasCached || runtimeInfo.has_value());
AD_CONTRACT_CHECK(!wasCached || runtimeInfo.has_value());

if (runtimeInfo.has_value()) {
if (wasCached) {
Expand All @@ -214,7 +214,7 @@ void Operation::updateRuntimeInformationOnSuccess(
// available.
_runtimeInfo.children_.clear();
for (auto* child : getChildren()) {
AD_CHECK(child);
AD_CONTRACT_CHECK(child);
_runtimeInfo.children_.push_back(
child->getRootOperation()->getRuntimeInfo());
}
Expand Down Expand Up @@ -280,7 +280,7 @@ void Operation::createRuntimeInfoFromEstimates() {
_runtimeInfo.descriptor_ = getDescriptor();

for (const auto& child : getChildren()) {
AD_CHECK(child);
AD_CONTRACT_CHECK(child);
child->getRootOperation()->createRuntimeInfoFromEstimates();
_runtimeInfo.children_.push_back(
child->getRootOperation()->getRuntimeInfo());
Expand Down
2 changes: 1 addition & 1 deletion src/engine/Operation.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ class Operation {
// Set the value of the `LIMIT` clause that will be applied to the result of
// this operation. May only be called if `supportsLimit` returns true.
void setLimit(uint64_t limit) {
AD_CHECK(supportsLimit());
AD_CONTRACT_CHECK(supportsLimit());
_limit = limit;
}

Expand Down
Loading

0 comments on commit 0f62bd8

Please sign in to comment.