-
Notifications
You must be signed in to change notification settings - Fork 37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Starting 'Select *' implementation #546
Changes from 9 commits
3ada215
fe6577e
7b8c3d8
c45ad7a
c176e1f
8cb8570
3bb4aaa
085f23d
4054695
43d7f9c
ed8ea69
c331fc4
afdbb93
c40cb3f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ | |
#include <sstream> | ||
#include <string> | ||
#include <utility> | ||
#include <variant> | ||
|
||
#include "../parser/RdfEscaping.h" | ||
#include "./Distinct.h" | ||
|
@@ -91,22 +92,41 @@ void QueryExecutionTree::setVariableColumns( | |
// _____________________________________________________________________________ | ||
template <QueryExecutionTree::ExportSubFormat format> | ||
ad_utility::stream_generator::stream_generator | ||
QueryExecutionTree::generateResults(const vector<string>& selectVars, | ||
QueryExecutionTree::generateResults(const SelectedVarsOrAsterisk & selectedVarsOrAsterisk, | ||
size_t limit, size_t offset) const { | ||
// They may trigger computation (but does not have to). | ||
shared_ptr<const ResultTable> resultTable = getResult(); | ||
LOG(DEBUG) << "Resolving strings for finished binary result...\n"; | ||
vector<std::optional<pair<size_t, ResultTable::ResultType>>> validIndices; | ||
for (auto var : selectVars) { | ||
if (ad_utility::startsWith(var, "TEXT(")) { | ||
var = var.substr(5, var.rfind(')') - 5); | ||
if(selectedVarsOrAsterisk.isAsterisk()) { | ||
list<string> orderedVariables = selectedVarsOrAsterisk.retrieveOrder(); | ||
auto allVars = getVariableColumns(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
for (const auto& var : orderedVariables) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
auto it = allVars.find(var); | ||
if (it != allVars.end()) { | ||
validIndices.emplace_back(pair<size_t, ResultTable::ResultType>( | ||
it->second, resultTable->getResultType(it->second))); | ||
allVars.erase(it); | ||
} else { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This else branch should also warn: |
||
validIndices.emplace_back(std::nullopt); | ||
} | ||
} | ||
auto it = getVariableColumns().find(var); | ||
if (it != getVariableColumns().end()) { | ||
validIndices.push_back(pair<size_t, ResultTable::ResultType>( | ||
it->second, resultTable->getResultType(it->second))); | ||
} else { | ||
validIndices.push_back(std::nullopt); | ||
for(const auto& var : allVars){ | ||
LOG(DEBUG) << "Variable " << var.first << " was not parsed!! \n"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
} | ||
} | ||
else { | ||
for (auto var : selectedVarsOrAsterisk.getSelectVariables()) { | ||
if (ad_utility::startsWith(var, "TEXT(")) { | ||
var = var.substr(5, var.rfind(')') - 5); | ||
} | ||
auto it = getVariableColumns().find(var); | ||
if (it != getVariableColumns().end()) { | ||
validIndices.emplace_back(pair<size_t, ResultTable::ResultType>( | ||
it->second, resultTable->getResultType(it->second))); | ||
} else { | ||
validIndices.emplace_back(std::nullopt); | ||
} | ||
} | ||
} | ||
if (validIndices.empty()) { | ||
|
@@ -123,48 +143,61 @@ QueryExecutionTree::generateResults(const vector<string>& selectVars, | |
|
||
template ad_utility::stream_generator::stream_generator | ||
QueryExecutionTree::generateResults<QueryExecutionTree::ExportSubFormat::CSV>( | ||
const vector<string>& selectVars, size_t limit, size_t offset) const; | ||
const SelectedVarsOrAsterisk & selectedVarsOrAsterisk, size_t limit, size_t offset) const; | ||
|
||
template ad_utility::stream_generator::stream_generator | ||
QueryExecutionTree::generateResults<QueryExecutionTree::ExportSubFormat::TSV>( | ||
const vector<string>& selectVars, size_t limit, size_t offset) const; | ||
const SelectedVarsOrAsterisk & selectedVarsOrAsterisk, size_t limit, size_t offset) const; | ||
|
||
template ad_utility::stream_generator::stream_generator QueryExecutionTree:: | ||
generateResults<QueryExecutionTree::ExportSubFormat::BINARY>( | ||
const vector<string>& selectVars, size_t limit, size_t offset) const; | ||
const SelectedVarsOrAsterisk & selectedVarsOrAsterisk, size_t limit, size_t offset) const; | ||
|
||
// ___________________________________________________________________________ | ||
QueryExecutionTree::ColumnIndicesAndTypes | ||
QueryExecutionTree::selectedVariablesToColumnIndices( | ||
const std::vector<string>& selectVariables, | ||
SelectedVarsOrAsterisk selectedVarsOrAsterisk, | ||
const ResultTable& resultTable) const { | ||
ColumnIndicesAndTypes exportColumns; | ||
for (auto var : selectVariables) { | ||
if (ad_utility::startsWith(var, "TEXT(")) { | ||
var = var.substr(5, var.rfind(')') - 5); | ||
if(selectedVarsOrAsterisk.isAsterisk()) { | ||
for(auto var: selectedVarsOrAsterisk.retrieveOrder()){ | ||
if (getVariableColumns().contains(var)) { | ||
auto columnIndex = getVariableColumns().at(var); | ||
exportColumns.push_back(VariableAndColumnIndex{ | ||
var, columnIndex, resultTable.getResultType(columnIndex)}); | ||
} else { | ||
exportColumns.emplace_back(std::nullopt); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also add the complementary warning here. |
||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also use your code from above here (including the warning etc.) |
||
if (getVariableColumns().contains(var)) { | ||
auto columnIndex = getVariableColumns().at(var); | ||
exportColumns.push_back(VariableAndColumnIndex{ | ||
var, columnIndex, resultTable.getResultType(columnIndex)}); | ||
} else { | ||
exportColumns.emplace_back(std::nullopt); | ||
} | ||
else { | ||
for (auto var : selectedVarsOrAsterisk.getSelectVariables()) { | ||
if (ad_utility::startsWith(var, "TEXT(")) { | ||
var = var.substr(5, var.rfind(')') - 5); | ||
} | ||
if (getVariableColumns().contains(var)) { | ||
auto columnIndex = getVariableColumns().at(var); | ||
exportColumns.push_back(VariableAndColumnIndex{ | ||
var, columnIndex, resultTable.getResultType(columnIndex)}); | ||
} else { | ||
exportColumns.emplace_back(std::nullopt); | ||
} | ||
} | ||
} | ||
return exportColumns; | ||
} | ||
|
||
// _____________________________________________________________________________ | ||
nlohmann::json QueryExecutionTree::writeResultAsQLeverJson( | ||
const vector<string>& selectVars, size_t limit, size_t offset, | ||
const SelectedVarsOrAsterisk & selectedVarsOrAsterisk, size_t limit, size_t offset, | ||
shared_ptr<const ResultTable> resultTable) const { | ||
// They may trigger computation (but does not have to). | ||
if (!resultTable) { | ||
resultTable = getResult(); | ||
} | ||
LOG(DEBUG) << "Resolving strings for finished binary result...\n"; | ||
ColumnIndicesAndTypes validIndices = | ||
selectedVariablesToColumnIndices(selectVars, *resultTable); | ||
selectedVariablesToColumnIndices(selectedVarsOrAsterisk, *resultTable); | ||
if (validIndices.empty()) { | ||
return {std::vector<std::string>()}; | ||
} | ||
|
@@ -175,7 +208,7 @@ nlohmann::json QueryExecutionTree::writeResultAsQLeverJson( | |
|
||
// _____________________________________________________________________________ | ||
nlohmann::json QueryExecutionTree::writeResultAsSparqlJson( | ||
const vector<string>& selectVars, size_t limit, size_t offset, | ||
const SelectedVarsOrAsterisk & selectedVarsOrAsterisk, size_t limit, size_t offset, | ||
shared_ptr<const ResultTable> resultTable) const { | ||
using nlohmann::json; | ||
|
||
|
@@ -186,7 +219,7 @@ nlohmann::json QueryExecutionTree::writeResultAsSparqlJson( | |
LOG(DEBUG) << "Finished computing the query result in the ID space. " | ||
"Resolving strings in result...\n"; | ||
ColumnIndicesAndTypes columns = | ||
selectedVariablesToColumnIndices(selectVars, *resultTable); | ||
selectedVariablesToColumnIndices(selectedVarsOrAsterisk, *resultTable); | ||
|
||
std::erase(columns, std::nullopt); | ||
|
||
|
@@ -197,7 +230,17 @@ nlohmann::json QueryExecutionTree::writeResultAsSparqlJson( | |
const IdTable& idTable = resultTable->_idTable; | ||
|
||
json result; | ||
result["head"]["vars"] = selectVars; | ||
|
||
if(selectedVarsOrAsterisk.isAsterisk()) { | ||
vector<string> vars_names; | ||
for(auto const & variable: selectedVarsOrAsterisk.retrieveOrder()) { | ||
vars_names.push_back(variable); | ||
} | ||
result["head"]["vars"] = vars_names; | ||
} | ||
else { | ||
result["head"]["vars"] = selectedVarsOrAsterisk.getSelectVariables(); | ||
} | ||
|
||
json bindings = json::array(); | ||
|
||
|
@@ -242,6 +285,7 @@ nlohmann::json QueryExecutionTree::writeResultAsSparqlJson( | |
}; | ||
|
||
for (size_t rowIndex = offset; rowIndex < upperBound; ++rowIndex) { | ||
// Due to be an 'nlohmann' object, object keys are alphabetically sorted! | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replace by |
||
nlohmann::ordered_json binding; | ||
for (const auto& column : columns) { | ||
const auto& currentId = idTable(rowIndex, column->_columnIndex); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,6 +18,7 @@ | |
#include "../util/streamable_generator.h" | ||
#include "./Operation.h" | ||
#include "./QueryExecutionContext.h" | ||
#include "../parser/ParsedQuery.h" | ||
|
||
using std::shared_ptr; | ||
using std::string; | ||
|
@@ -101,17 +102,19 @@ class QueryExecutionTree { | |
ResultTable::ResultType _resultType; | ||
}; | ||
|
||
using SelectedVarsOrAsterisk = ParsedQuery::SelectedVarsOrAsterisk; | ||
|
||
using ColumnIndicesAndTypes = vector<std::optional<VariableAndColumnIndex>>; | ||
|
||
// Returns a vector where the i-th element contains the column index and | ||
// `ResultType` of the i-th `selectVariable` in the `resultTable` | ||
ColumnIndicesAndTypes selectedVariablesToColumnIndices( | ||
const std::vector<string>& selectVariables, | ||
SelectedVarsOrAsterisk selectedVarsOrAsterisk, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this not a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think you modify it in place. |
||
const ResultTable& resultTable) const; | ||
|
||
template <ExportSubFormat format> | ||
ad_utility::stream_generator::stream_generator generateResults( | ||
const vector<string>& selectVars, size_t limit = MAX_NOF_ROWS_IN_RESULT, | ||
const SelectedVarsOrAsterisk & selectedVarsOrAsterisk, size_t limit = MAX_NOF_ROWS_IN_RESULT, | ||
size_t offset = 0) const; | ||
|
||
// Generate an RDF graph in turtle format for a CONSTRUCT query. | ||
|
@@ -131,11 +134,11 @@ class QueryExecutionTree { | |
size_t offset, std::shared_ptr<const ResultTable> res) const; | ||
|
||
nlohmann::json writeResultAsQLeverJson( | ||
const vector<string>& selectVars, size_t limit, size_t offset, | ||
const SelectedVarsOrAsterisk & selectedVarsOrAsterisk, size_t limit, size_t offset, | ||
shared_ptr<const ResultTable> resultTable = nullptr) const; | ||
|
||
nlohmann::json writeResultAsSparqlJson( | ||
const vector<string>& selectVars, size_t limit, size_t offset, | ||
const SelectedVarsOrAsterisk & selectedVarsOrAsterisk, size_t limit, size_t offset, | ||
shared_ptr<const ResultTable> preComputedResult = nullptr) const; | ||
|
||
const std::vector<size_t>& resultSortedOn() const { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -169,10 +169,19 @@ Awaitable<json> Server::composeResponseQleverJson( | |
j["query"] = query._originalString; | ||
j["status"] = "OK"; | ||
j["warnings"] = qet.collectWarnings(); | ||
j["selected"] = | ||
query.hasSelectClause() | ||
? query.selectClause()._selectedVariables | ||
: std::vector<std::string>{"?subject", "?predicate", "?object"}; | ||
if(query.hasSelectClause()){ | ||
if(query.selectClause()._varsOrAsterisk.isAsterisk()) { | ||
auto list = query.selectClause()._varsOrAsterisk.retrieveOrder(); | ||
std::vector<string> result{ list.begin(),list.end() }; | ||
j["selected"] = result; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We will make |
||
} | ||
else { | ||
j["selected"] = query.selectClause()._varsOrAsterisk.getSelectVariables(); | ||
} | ||
} | ||
else { | ||
j["selected"] = std::vector<std::string>{"?subject", "?predicate", "?object"}; | ||
} | ||
|
||
j["runtimeInformation"] = RuntimeInformation::ordered_json( | ||
qet.getRootOperation()->getRuntimeInfo()); | ||
|
@@ -184,7 +193,7 @@ Awaitable<json> Server::composeResponseQleverJson( | |
requestTimer.cont(); | ||
j["res"] = query.hasSelectClause() | ||
? qet.writeResultAsQLeverJson( | ||
query.selectClause()._selectedVariables, limit, | ||
query.selectClause()._varsOrAsterisk, limit, | ||
offset, std::move(resultTable)) | ||
: qet.writeRdfGraphJson(query.constructClause(), limit, | ||
offset, std::move(resultTable)); | ||
|
@@ -220,8 +229,9 @@ Awaitable<json> Server::composeResponseSparqlJson( | |
std::min(query._limit.value_or(MAX_NOF_ROWS_IN_RESULT), maxSend); | ||
size_t offset = query._offset.value_or(0); | ||
requestTimer.cont(); | ||
j = qet.writeResultAsSparqlJson(query.selectClause()._selectedVariables, | ||
j = qet.writeResultAsSparqlJson(query.selectClause()._varsOrAsterisk, | ||
limit, offset, std::move(resultTable)); | ||
|
||
requestTimer.stop(); | ||
return j; | ||
}; | ||
|
@@ -238,7 +248,7 @@ Server::composeResponseSepValues(const ParsedQuery& query, | |
size_t offset = query._offset.value_or(0); | ||
return query.hasSelectClause() | ||
? qet.generateResults<format>( | ||
query.selectClause()._selectedVariables, limit, offset) | ||
query.selectClause()._varsOrAsterisk, limit, offset) | ||
: qet.writeRdfGraphSeparatedValues<format>( | ||
query.constructClause(), limit, offset, qet.getResult()); | ||
}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
call them
orderedVariablesFromQuery
instead oforderedVariables