diff --git a/src/engine/CheckUsePatternTrick.cpp b/src/engine/CheckUsePatternTrick.cpp index 0cae765d5f..b4c9a76447 100644 --- a/src/engine/CheckUsePatternTrick.cpp +++ b/src/engine/CheckUsePatternTrick.cpp @@ -136,6 +136,12 @@ void addValuesClause(ParsedQuery::GraphPattern& graphPattern, for (const auto& foundValue : foundClauses) { addValuesClause(graphPattern, foundValue, false); } + + if (foundClauses.empty()) { + for (auto& pattern : graphPattern._graphPatterns) { + addValuesClauseToPattern(pattern, std::nullopt); + } + } } // __________________________________________________________________________ @@ -145,9 +151,9 @@ bool addValuesClauseToPattern(parsedQuery::GraphPatternOperation& operation, addValuesClause(pattern, result); return false; }; - // TODO Don't pass an optional to this function. - AD_CORRECTNESS_CHECK(result.has_value()); - const auto& variables = result.value()._inlineValues._variables; + const std::vector emptyVars{}; + const auto& variables = + result.has_value() ? result.value()._inlineValues._variables : emptyVars; auto anyVar = [&](auto f) { return ql::ranges::any_of(variables, f); }; return operation.visit([&](auto&& arg) -> bool { using T = std::decay_t; @@ -169,6 +175,9 @@ bool addValuesClauseToPattern(parsedQuery::GraphPatternOperation& operation, })) { return check(arg.get()._rootGraphPattern); } else { + // Also recurse into the subquery, but not with the given `VALUES` + // clause. + addValuesClause(arg.get()._rootGraphPattern, std::nullopt); return false; } } else if constexpr (std::is_same_v) { @@ -200,9 +209,10 @@ bool addValuesClauseToPattern(parsedQuery::GraphPatternOperation& operation, static_assert( std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v); - // The `TransPath` is set up later in the query planning, when this - // function should not be called anymore. - AD_FAIL(); + // TODO This is just an optimization, so we can always just omit + // it, but it would be nice to also apply this optimization for those + // types of queries. + return false; } }); } diff --git a/src/engine/QueryPlanner.cpp b/src/engine/QueryPlanner.cpp index 8a6e302de3..d03000abf4 100644 --- a/src/engine/QueryPlanner.cpp +++ b/src/engine/QueryPlanner.cpp @@ -205,12 +205,15 @@ std::vector QueryPlanner::createExecutionTrees( } // _____________________________________________________________________________ -QueryExecutionTree QueryPlanner::createExecutionTree(ParsedQuery& pq, +QueryExecutionTree QueryPlanner::createExecutionTree(ParsedQuery& pqIn, bool isSubquery) { try { + ParsedQuery copy; if (!isSubquery) { - checkUsePatternTrick::addValuesClause(pq._rootGraphPattern); + copy = pqIn; + checkUsePatternTrick::addValuesClause(copy._rootGraphPattern); } + auto& pq = isSubquery ? pqIn : copy; auto lastRow = createExecutionTrees(pq, isSubquery); auto minInd = findCheapestExecutionTree(lastRow); LOG(DEBUG) << "Done creating execution plan" << std::endl;