Skip to content

Commit

Permalink
Resurrect special predicates
Browse files Browse the repository at this point in the history
  • Loading branch information
ullingerc committed Nov 18, 2024
1 parent 426359b commit 6e8e57d
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 27 deletions.
22 changes: 13 additions & 9 deletions src/engine/QueryPlanner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -757,15 +757,19 @@ auto QueryPlanner::seedWithScansAndText(
"necessary also rebuild the index.");
}

// TODO<ullingerc>
// const auto& input = node.triple_.p_._iri;
// if ((input.starts_with(MAX_DIST_IN_METERS) ||
// input.starts_with(NEAREST_NEIGHBORS)) &&
// input.ends_with('>')) {
// pushPlan(makeSubtreePlan<SpatialJoin>(_qec, node.triple_, std::nullopt,
// std::nullopt));
// continue;
// }
// Backward compatibility with spatial search predicates
const auto& input = node.triple_.p_._iri;
if ((input.starts_with(MAX_DIST_IN_METERS) ||
input.starts_with(NEAREST_NEIGHBORS)) &&
input.ends_with('>')) {
parsedQuery::SpatialQuery config{node.triple_};
pushPlan(makeSubtreePlan<SpatialJoin>(
_qec,
std::make_shared<SpatialJoinConfiguration>(
config.toSpatialJoinConfiguration()),
std::nullopt, std::nullopt));
continue;
}

if (node.triple_.p_._iri == HAS_PREDICATE_PREDICATE) {
pushPlan(makeSubtreePlan<HasPredicateScan>(_qec, node.triple_));
Expand Down
19 changes: 2 additions & 17 deletions src/global/Constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,9 @@ constexpr inline std::string_view MATCHINGWORD_VARIABLE_PREFIX =
constexpr inline std::string_view LANGUAGE_PREDICATE =
makeQleverInternalIriConst<"langtag">();

// this predicate is one of the supported identifiers for the SpatialJoin class.
// It joins the two objects, if their distance is smaller or equal to the
// maximum distance, which needs to be given in the predicate as well. The
// syntax for the predicate needs to be like this:
// <max-distance-in-meters:XXXX>, where XXXX needs to be replaced by an integer
// number.
// For backward compatibility: invocation of SpatialJoin via special predicates.
static const std::string MAX_DIST_IN_METERS = "<max-distance-in-meters:";
static const std::string NEAREST_NEIGHBORS = "<nearest-neighbors:";
static constexpr auto MAX_DIST_IN_METERS_REGEX =
ctll::fixed_string{"<max-distance-in-meters:(?<dist>[0-9]+)>"};

Expand All @@ -121,17 +117,6 @@ static constexpr auto MAX_DIST_IN_METERS_REGEX =
// estimated number of results.
static const size_t SPATIAL_JOIN_MAX_DIST_SIZE_ESTIMATE = 1000;

// TODO<ullingerc> will be obsolete, remove
// This predicate is one of the supported identifiers for the SpatialJoin class.
// For a given triple of the form ?a <nearest-neighbors:XXXX:YYYY> ?b, it will
// produce for each value of ?a the nearest neighbors ?b to ?a. The number of
// nearest neighbors must be limited by replacing the XXXX with an integer.
// Optionally the search range can be limited by giving YYYY as an integer
// representing meters.
static const std::string NEAREST_NEIGHBORS = "<nearest-neighbors:";
static constexpr auto NEAREST_NEIGHBORS_REGEX = ctll::fixed_string{
"<nearest-neighbors:(?<results>[0-9]+)(:(?<dist>[0-9]+))?>"};

// TODO<joka921> Move them to their own file, make them strings, remove
// duplications, etc.
constexpr inline char XSD_STRING[] = "http://www.w3.org/2001/XMLSchema#string";
Expand Down
42 changes: 42 additions & 0 deletions src/parser/SpatialQuery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,46 @@ SpatialJoinConfiguration SpatialQuery::toSpatialJoinConfiguration() const {
}
}

// ____________________________________________________________________________
SpatialQuery::SpatialQuery(const SparqlTriple& triple) {
AD_CONTRACT_CHECK(triple.p_.isIri(),
"The config triple for SpatialJoin must have a special IRI "
"as predicate.");
const std::string& input = triple.p_._iri;

if (input.starts_with(NEAREST_NEIGHBORS)) {
throw SpatialSearchException(
"The special predicate <nearest-neighbors:...> is no longer supported "
"due to confusing semantics. Please use SERVICE spatialSearch: {...} "
"instead. For information on its usage, see the QLever Wiki.");
}

// Add variables to configuration object
AD_CONTRACT_CHECK(triple.s_.isVariable() && triple.o_.isVariable(),
"Currently, SpatialJoin needs two variables");
setVariable("left", triple.s_, left_);
setVariable("right", triple.o_, right_);

// Helper to convert a ctre match to an integer
auto matchToInt = [](std::string_view match) -> std::optional<size_t> {
if (match.size() > 0) {
size_t res = 0;
std::from_chars(match.data(), match.data() + match.size(), res);
return res;
}
return std::nullopt;
};

// Extract max distance from predicate
if (auto match = ctre::match<MAX_DIST_IN_METERS_REGEX>(input)) {
maxDist_ = matchToInt(match.get<"dist">());
AD_CORRECTNESS_CHECK(maxDist_.has_value());
} else {
AD_THROW(absl::StrCat("Tried to perform spatial join with unknown triple ",
input,
". This must be a valid spatial condition like ",
"<max-distance-in-meters:50>."));
}
}

} // namespace parsedQuery
4 changes: 4 additions & 0 deletions src/parser/SpatialQuery.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ struct SpatialQuery : MagicServiceQuery {
SpatialQuery& operator=(SpatialQuery&& a) noexcept = default;
virtual ~SpatialQuery() = default;

// Alternative constructor for backward compatibility (allows initializing a
// SpatialJoin using a magic predicate)
SpatialQuery(const SparqlTriple& triple);

// See MagicServiceQuery
void addParameter(const SparqlTriple& triple) override;

Expand Down
1 change: 0 additions & 1 deletion test/engine/SpatialJoinTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -654,7 +654,6 @@ void testMultiplicitiesOrSizeEstimate(bool addLeftChildFirst,
ASSERT_NE(spatialJoin->onlyForTestingGetRightChild(), nullptr);
// the size should be at most 49, because both input tables have 7 rows and
// it is assumed, that in the worst case the whole cross product is build
// TODO<ullingerc> Segfault here
auto estimate =
spatialJoin->onlyForTestingGetLeftChild()->getSizeEstimate() *
spatialJoin->onlyForTestingGetRightChild()->getSizeEstimate();
Expand Down

0 comments on commit 6e8e57d

Please sign in to comment.