diff --git a/src/engine/Service.cpp b/src/engine/Service.cpp index d2570a871c..8abd2666dd 100644 --- a/src/engine/Service.cpp +++ b/src/engine/Service.cpp @@ -29,7 +29,9 @@ Service::Service(QueryExecutionContext* qec, "\"Michael Fred Phelps, II\"@en"}, {"", - "\"Birgit Fischer-Schmidt\"@en"}}; + // 73643}}; + "\"73264732\"^^"}}; + // "\"Birgit Fischer-Schmidt\"@en"}}; resultAsValues_ = std::make_unique(qec, std::move(sparqlValues)); } diff --git a/src/engine/Values.cpp b/src/engine/Values.cpp index 870033479b..49df898ec9 100644 --- a/src/engine/Values.cpp +++ b/src/engine/Values.cpp @@ -29,7 +29,7 @@ string Values::asStringImpl(size_t indent) const { } os << ") {"; for (size_t i = 0; i < _values._values.size(); i++) { - const vector& v = _values._values[i]; + const vector& v = _values._values[i]; os << "("; for (size_t j = 0; j < v.size(); j++) { os << v[j]; @@ -57,7 +57,7 @@ string Values::getDescriptor() const { } os << " and values "; for (size_t i = 0; i < _values._values.size(); i++) { - const vector& v = _values._values[i]; + const vector& v = _values._values[i]; os << "("; for (size_t j = 0; j < v.size(); j++) { os << v[j]; @@ -107,13 +107,13 @@ void Values::computeMultiplicities() { return; } _multiplicities.resize(_values._variables.size()); - ad_utility::HashSet values; + ad_utility::HashSet values; for (size_t col = 0; col < _values._variables.size(); col++) { values.clear(); size_t count = 0; size_t distinct = 0; for (size_t j = 0; j < _values._values.size(); j++) { - const std::string& v = _values._values[j][col]; + const TripleComponent& v = _values._values[j][col]; count++; if (values.count(v) == 0) { distinct++; @@ -133,7 +133,8 @@ void Values::computeResult(ResultTable* result) { ResultTable::ResultType::KB); size_t resWidth = getResultWidth(); - CALL_FIXED_SIZE_1(resWidth, writeValues, &result->_idTable, index, _values); + CALL_FIXED_SIZE_1(resWidth, writeValues, &result->_idTable, index, _values, + result->_localVocab); } auto Values::sanitizeValues(SparqlValues&& values) -> SparqlValues { @@ -187,23 +188,27 @@ auto Values::sanitizeValues(SparqlValues&& values) -> SparqlValues { template void Values::writeValues(IdTable* res, const Index& index, - const SparqlValues& values) { + const SparqlValues& values, + std::shared_ptr localVocab) { IdTableStatic result = res->moveToStatic(); result.resize(values._values.size()); size_t numActuallyWritten = 0; size_t numSkipped = 0; for (const auto& row : values._values) { for (size_t colIdx = 0; colIdx < result.cols(); colIdx++) { - Id id; - if (!index.getId(row[colIdx], &id)) { - getWarnings().push_back("The word " + row[colIdx] + - " is not part of the vocabulary."); + const TripleComponent& tc = row[colIdx]; + std::optional id = tc.toValueId(index.getVocab()); + if (!id) { + AD_CHECK(tc.isString()); + getWarnings().push_back( + absl::StrCat("The word ", row[colIdx].toString(), + " is not part of the vocabulary.")); numSkipped++; // this goto is a continue in the outer loop. The current row was not // sucessfully written, so the numActuallyWritten index is not advanced goto skipRow; } - result(numActuallyWritten, colIdx) = id; + result(numActuallyWritten, colIdx) = id.value(); } numActuallyWritten++; skipRow:; // the label for the goto. Jumping to this label is basically diff --git a/src/engine/Values.h b/src/engine/Values.h index 4ca85eeb14..b4d4977b34 100644 --- a/src/engine/Values.h +++ b/src/engine/Values.h @@ -53,7 +53,8 @@ class Values : public Operation { template void writeValues(IdTable* res, const Index& index, - const SparqlValues& values); + const SparqlValues& values, + std::shared_ptr localVocab); /// remove all completely undefined values and variables /// throw if nothing remains diff --git a/src/parser/GraphPatternOperation.h b/src/parser/GraphPatternOperation.h index 7acf96e93f..b05b03c898 100644 --- a/src/parser/GraphPatternOperation.h +++ b/src/parser/GraphPatternOperation.h @@ -31,7 +31,7 @@ class SparqlValues { // The variables to which the values will be bound std::vector _variables; // A table storing the values in their string form - std::vector> _values; + std::vector> _values; }; /// A `SERVICE` clause. diff --git a/src/parser/TripleComponent.h b/src/parser/TripleComponent.h index cd9cb19b72..072b462533 100644 --- a/src/parser/TripleComponent.h +++ b/src/parser/TripleComponent.h @@ -84,6 +84,12 @@ class TripleComponent { /// Equality comparison between two `TripleComponent`s. bool operator==(const TripleComponent&) const = default; + /// Hash value for `TripleComponent` object. + template + friend H AbslHashValue(H h, const TripleComponent& tc) { + return H::combine(std::move(h), tc._variant); + } + /// Check which type the underlying variants hold. [[nodiscard]] bool isString() const { return std::holds_alternative(_variant); diff --git a/src/parser/sparqlParser/SparqlQleverVisitor.cpp b/src/parser/sparqlParser/SparqlQleverVisitor.cpp index cc2e45617f..e88e6e0dab 100644 --- a/src/parser/sparqlParser/SparqlQleverVisitor.cpp +++ b/src/parser/sparqlParser/SparqlQleverVisitor.cpp @@ -729,7 +729,7 @@ SparqlValues Visitor::visit(Parser::InlineDataFullContext* ctx) { } // ____________________________________________________________________________________ -vector Visitor::visit(Parser::DataBlockSingleContext* ctx) { +vector Visitor::visit(Parser::DataBlockSingleContext* ctx) { if (ctx->NIL()) reportError(ctx, "No values were specified in DataBlock." @@ -738,16 +738,19 @@ vector Visitor::visit(Parser::DataBlockSingleContext* ctx) { } // ____________________________________________________________________________________ -std::string Visitor::visit(Parser::DataBlockValueContext* ctx) { +TripleComponent Visitor::visit(Parser::DataBlockValueContext* ctx) { // Return a string if (ctx->iri()) { return visit(ctx->iri()); } else if (ctx->rdfLiteral()) { - // TODO This is still wrong for XSD literals - return visit(ctx->rdfLiteral()); + return TurtleStringParser::parseTripleObject( + visit(ctx->rdfLiteral())); } else if (ctx->numericLiteral()) { + return std::visit([](auto intOrDouble) { + return TripleComponent{intOrDouble}; }, + visitTypesafe(ctx->numericLiteral())); // TODO implement - reportError(ctx, "Numbers in values clauses are not supported."); + // reportError(ctx, "Numbers in values clauses are not supported."); } else if (ctx->booleanLiteral()) { // TODO implement reportError(ctx, "Booleans in values clauses are not supported."); diff --git a/src/parser/sparqlParser/SparqlQleverVisitor.h b/src/parser/sparqlParser/SparqlQleverVisitor.h index 53ff1b627c..030fc83740 100644 --- a/src/parser/sparqlParser/SparqlQleverVisitor.h +++ b/src/parser/sparqlParser/SparqlQleverVisitor.h @@ -204,9 +204,11 @@ class SparqlQleverVisitor { [[nodiscard]] parsedQuery::SparqlValues visit( Parser::InlineDataFullContext* ctx); - [[nodiscard]] vector visit(Parser::DataBlockSingleContext* ctx); + [[nodiscard]] vector visit( + Parser::DataBlockSingleContext* ctx); - [[nodiscard]] std::string visit(Parser::DataBlockValueContext* ctx); + [[nodiscard]] TripleComponent visitTypesafe( + Parser::DataBlockValueContext* ctx); [[nodiscard]] GraphPatternOperation visit( Parser::MinusGraphPatternContext* ctx); diff --git a/test/SparqlAntlrParserTest.cpp b/test/SparqlAntlrParserTest.cpp index d0a1df4267..d01e05c292 100644 --- a/test/SparqlAntlrParserTest.cpp +++ b/test/SparqlAntlrParserTest.cpp @@ -552,7 +552,7 @@ TEST(SparqlParser, DataBlock) { auto expectDataBlockFails = ExpectParseFails<&Parser::dataBlock>(); expectDataBlock( "?test { \"foo\" }", - m::Values(vector{"?test"}, vector>{{"\"foo\""}})); + m::Values(vector{"?test"}, vector>{{"\"foo\""}})); // These are not implemented yet in dataBlockValue // (numericLiteral/booleanLiteral) // TODO implement diff --git a/test/SparqlAntlrParserTestHelpers.h b/test/SparqlAntlrParserTestHelpers.h index a5364d6e76..f3319bbaa6 100644 --- a/test/SparqlAntlrParserTestHelpers.h +++ b/test/SparqlAntlrParserTestHelpers.h @@ -11,6 +11,7 @@ #include "engine/sparqlExpressions/SparqlExpressionPimpl.h" #include "parser/Alias.h" #include "parser/ParsedQuery.h" +#include "parser/TripleComponent.h" #include "parser/SparqlParserHelpers.h" #include "parser/data/OrderKey.h" #include "parser/data/VarOrTerm.h" @@ -423,9 +424,9 @@ auto GroupByVariables = testing::UnorderedElementsAreArray(vars)); }; -auto Values = - [](const vector& vars, - const vector>& values) -> Matcher { +auto Values = [](const vector& vars, + const vector>& values) + -> Matcher { // TODO Refactor GraphPatternOperation::Values / SparqlValues s.t. this // becomes a trivial Eq matcher. using SparqlValues = p::SparqlValues; @@ -436,7 +437,7 @@ auto Values = }; auto InlineData = [](const vector& vars, - const vector>& values) + const vector>& values) -> Matcher { // TODO Refactor GraphPatternOperation::Values / SparqlValues s.t. this // becomes a trivial Eq matcher. diff --git a/test/SparqlParserTest.cpp b/test/SparqlParserTest.cpp index bf487f7041..7dd4dc2ef2 100644 --- a/test/SparqlParserTest.cpp +++ b/test/SparqlParserTest.cpp @@ -248,7 +248,7 @@ TEST(ParserTest, testParse) { vector vvars = {"?a"}; ASSERT_EQ(vvars, values1._variables); - vector> vvals = {{"<1>"}, {"\"2\""}}; + vector> vvals = {{"<1>"}, {"\"2\""}}; ASSERT_EQ(vvals, values1._values); vvars = {"?b", "?c"}; @@ -273,7 +273,7 @@ TEST(ParserTest, testParse) { vector vvars = {"?a"}; ASSERT_EQ(vvars, values1._variables); - vector> vvals = {{""}}; + vector> vvals = {{""}}; ASSERT_EQ(vvals, values1._values); vvars = {"?b", "?c"}; @@ -306,7 +306,7 @@ TEST(ParserTest, testParse) { const auto& values1 = std::get(pq.children()[0])._inlineValues; vector vvars = {"?citytype"}; ASSERT_EQ(vvars, values1._variables); - vector> vvals = { + vector> vvals = { {""}, {""}}; ASSERT_EQ(vvals, values1._values);