diff --git a/src/libqlever/LibQLeverExample.cpp b/src/libqlever/LibQLeverExample.cpp index dbc0ffe2e6..ccf5ef869c 100644 --- a/src/libqlever/LibQLeverExample.cpp +++ b/src/libqlever/LibQLeverExample.cpp @@ -2,15 +2,43 @@ // Chair of Algorithms and Data Structures. // Author: Johannes Kalmbach +#include + #include #include "libqlever/Qlever.h" +#include "util/Timer.h" + +static const std::string warmup1 = ""; +static const std::string warmup2 = ""; + +static const std::string queryTemplate = R"( +SELECT * { + #INPUTS# + SERVICE ql:named-cached-query-warmup1 {} + SERVICE ql:named-cached-query-warmup2 {} +} +)"; + +std::vector inputs{""}; int main() { qlever::QleverConfig config; config.baseName = "exampleIndex"; config.inputFiles.emplace_back("/dev/stdin", qlever::Filetype::Turtle); + config.vocabularyType_ = + ad_utility::VocabularyType{ad_utility::VocabularyType::Enum::InMemory}; qlever::Qlever::buildIndex(config); qlever::Qlever qlever{config}; - std::cout << qlever.query("SELECT * {?s ?p ?o}") << std::endl; + qlever.pinNamed(warmup1, "warmup1"); + qlever.pinNamed(warmup2, "warmup2"); + + for (std::string_view input : inputs) { + auto query = absl::StrReplaceAll(queryTemplate, + {{std::string_view{"#INPUTS#"}, input}}); + ad_utility::Timer t{ad_utility::Timer::Started}; + auto result = qlever.query(std::move(query)); + std::cout << "retrieved a query result of size " << result.size() << " in " + << t.msecs().count() << "ms\n"; + } } diff --git a/src/libqlever/Qlever.cpp b/src/libqlever/Qlever.cpp index cc37562dde..fb4c77eaf6 100644 --- a/src/libqlever/Qlever.cpp +++ b/src/libqlever/Qlever.cpp @@ -4,6 +4,8 @@ #include "libqlever/Qlever.h" +#include "index/IndexImpl.h" + namespace qlever { static std::string getStxxlConfigFileName(const string& location) { return absl::StrCat(location, ".stxxl"); @@ -51,6 +53,8 @@ Qlever::Qlever(const QleverConfig& config) enablePatternTrick_ = !config.noPatterns; index_.loadAllPermutations() = !config.onlyPsoAndPos; + index_.getImpl().setVocabularyTypeForIndexBuilding(config.vocabularyType_); + // Init the index. index_.createFromOnDiskIndex(config.baseName); // TODO Enable the loading of the text index via the QLever lib. @@ -121,7 +125,7 @@ void Qlever::buildIndex(QleverConfig config) { // ___________________________________________________________________________ std::string Qlever::query(std::string query) { QueryExecutionContext qec{index_, &cache_, allocator_, - sortPerformanceEstimator_}; + sortPerformanceEstimator_, &namedQueryCache_}; auto parsedQuery = SparqlParser::parseQuery(query); auto handle = std::make_shared>(); QueryPlanner qp{&qec, handle}; @@ -156,4 +160,43 @@ std::string Qlever::query(std::string query) { } return result; } +// ___________________________________________________________________________ +// TODO A lot of code duplication here. +void Qlever::pinNamed(std::string query, std::string name) { + QueryExecutionContext qec{index_, &cache_, allocator_, + sortPerformanceEstimator_, &namedQueryCache_}; + qec.pinWithExplicitName() = std::move(name); + auto parsedQuery = SparqlParser::parseQuery(query); + auto handle = std::make_shared>(); + QueryPlanner qp{&qec, handle}; + qp.setEnablePatternTrick(enablePatternTrick_); + auto qet = qp.createExecutionTree(parsedQuery); + qet.isRoot() = true; + auto& limitOffset = parsedQuery._limitOffset; + + // TODO For cancellation we have to call + // `recursivelySetCancellationHandle` (see `Server::parseAndPlan`). + + // TODO The following interface looks fishy and should be + // incorporated directly in the query planner or somewhere else. + // (it is used identically in `Server.cpp`. + + // Make sure that the offset is not applied again when exporting the result + // (it is already applied by the root operation in the query execution + // tree). Note that we don't need this for the limit because applying a + // fixed limit is idempotent. + AD_CORRECTNESS_CHECK(limitOffset._offset >= + qet.getRootOperation()->getLimit()._offset); + limitOffset._offset -= qet.getRootOperation()->getLimit()._offset; + + ad_utility::Timer timer{ad_utility::Timer::Started}; + auto responseGenerator = ExportQueryExecutionTrees::computeResult( + parsedQuery, qet, ad_utility::MediaType::sparqlJson, timer, + std::move(handle)); + std::string result; + std::cout << "Writing the result:" << std::endl; + for (const auto& batch : responseGenerator) { + result += batch; + } +} } // namespace qlever diff --git a/src/libqlever/Qlever.h b/src/libqlever/Qlever.h index 88ac4fc042..0a50620670 100644 --- a/src/libqlever/Qlever.h +++ b/src/libqlever/Qlever.h @@ -13,6 +13,7 @@ #include #include "engine/ExportQueryExecutionTrees.h" +#include "engine/NamedQueryCache.h" #include "engine/QueryExecutionContext.h" #include "engine/QueryPlanner.h" #include "global/RuntimeParameters.h" @@ -84,6 +85,7 @@ class Qlever { ad_utility::AllocatorWithLimit allocator_; SortPerformanceEstimator sortPerformanceEstimator_; Index index_; + NamedQueryCache namedQueryCache_; bool enablePatternTrick_; static inline std::ostringstream ignoreLogStream;