3131import org .eclipse .rdf4j .query .algebra .Filter ;
3232import org .eclipse .rdf4j .query .algebra .Join ;
3333import org .eclipse .rdf4j .query .algebra .Order ;
34+ import org .eclipse .rdf4j .query .algebra .OrderElem ;
3435import org .eclipse .rdf4j .query .algebra .Projection ;
3536import org .eclipse .rdf4j .query .algebra .ProjectionElem ;
3637import org .eclipse .rdf4j .query .algebra .QueryModelNode ;
@@ -104,7 +105,7 @@ private boolean transform(Join node, LmdbQueryAccess queryAccess) {
104105 LmdbLftjPlanningHints planningHints = planningTarget != null ? planningTarget .planningHints ()
105106 : collectPlanningHints (operands , List .of ());
106107 String cacheKey = LmdbLftjPreparedPlanCache .normalizedKey (patterns , configuredIndexes , outputBindings ,
107- inequalityConstraints );
108+ inequalityConstraints , planningHints );
108109 LmdbLftjPlanner .PlanningResult plan = queryAccess .cachedPlanningResult (cacheKey );
109110 if (plan == null ) {
110111 plan = planner .plan (fallbackExpr , patterns , configuredIndexes , outputBindings , inequalityConstraints ,
@@ -167,6 +168,7 @@ private PlanningTarget tryExtractPlanningTarget(Join node, List<TupleExpr> opera
167168 List <Filter > filters = new ArrayList <>();
168169 Extension extension = null ;
169170 Projection projection = null ;
171+ LinkedHashSet <String > outerRequiredVariables = new LinkedHashSet <>();
170172
171173 while (traversal .getParentNode () instanceof UnaryTupleOperator
172174 && ((UnaryTupleOperator ) traversal .getParentNode ()).getArg () == traversal ) {
@@ -195,7 +197,13 @@ private PlanningTarget tryExtractPlanningTarget(Join node, List<TupleExpr> opera
195197 }
196198 continue ;
197199 }
198- if (parent instanceof Distinct || parent instanceof Order ) {
200+ if (parent instanceof Distinct ) {
201+ rootReplaceable = false ;
202+ traversal = parent ;
203+ continue ;
204+ }
205+ if (parent instanceof Order ) {
206+ collectOrderRequiredVariables ((Order ) parent , Set .copyOf (visibleVariables ), outerRequiredVariables );
199207 rootReplaceable = false ;
200208 traversal = parent ;
201209 continue ;
@@ -221,7 +229,7 @@ private PlanningTarget tryExtractPlanningTarget(Join node, List<TupleExpr> opera
221229 .stream ()
222230 .anyMatch (filterRewrite -> filterRewrite .residualCondition () != null );
223231 List <LmdbLftjPlan .OutputBinding > outputBindings = collectOutputBindings (projection , extension , visibleVariables ,
224- filterPartition .requiredVariables (), preserveOuterOperators );
232+ filterPartition .requiredVariables (), List . copyOf ( outerRequiredVariables ), preserveOuterOperators );
225233 if (outputBindings == null ) {
226234 return null ;
227235 }
@@ -317,9 +325,11 @@ private boolean isNamedVariable(Var var) {
317325 }
318326
319327 private List <LmdbLftjPlan .OutputBinding > collectOutputBindings (Projection projection , Extension extension ,
320- List <String > visibleVariables , List <String > requiredVariables , boolean preserveOuterOperators ) {
328+ List <String > visibleVariables , List <String > requiredVariables , List <String > outerRequiredVariables ,
329+ boolean preserveOuterOperators ) {
321330 if (preserveOuterOperators ) {
322- return collectVisibleInputBindings (projection , extension , visibleVariables , requiredVariables );
331+ return collectVisibleInputBindings (projection , extension , visibleVariables , requiredVariables ,
332+ outerRequiredVariables );
323333 }
324334 if (projection == null ) {
325335 return extension == null ? List .of () : null ;
@@ -359,8 +369,8 @@ private List<LmdbLftjPlan.OutputBinding> collectOutputBindings(Projection projec
359369 }
360370
361371 private List <LmdbLftjPlan .OutputBinding > collectVisibleInputBindings (Projection projection , Extension extension ,
362- List <String > visibleVariables , List <String > requiredVariables ) {
363- LinkedHashSet <String > neededInputs = new LinkedHashSet <>(requiredVariables );
372+ List <String > visibleVariables , List <String > requiredVariables , List < String > outerRequiredVariables ) {
373+ LinkedHashSet <String > neededInputs = new LinkedHashSet <>();
364374 if (projection != null ) {
365375 for (ProjectionElem projectionElem : projection .getProjectionElemList ().getElements ()) {
366376 neededInputs .add (projectionElem .getName ());
@@ -370,18 +380,28 @@ private List<LmdbLftjPlan.OutputBinding> collectVisibleInputBindings(Projection
370380 } else {
371381 neededInputs .addAll (visibleVariables );
372382 }
383+ neededInputs .addAll (requiredVariables );
384+ neededInputs .addAll (outerRequiredVariables );
373385 if (extension != null ) {
374386 neededInputs = resolveExtensionInputs (neededInputs , extension , Set .copyOf (visibleVariables ));
375387 }
376388 List <LmdbLftjPlan .OutputBinding > outputBindings = new ArrayList <>();
377- for (String visibleVariable : visibleVariables ) {
378- if (neededInputs .contains (visibleVariable )) {
379- outputBindings .add (new LmdbLftjPlan .OutputBinding (visibleVariable , visibleVariable ));
389+ Set <String > visible = Set .copyOf (visibleVariables );
390+ for (String neededInput : neededInputs ) {
391+ if (visible .contains (neededInput )) {
392+ outputBindings .add (new LmdbLftjPlan .OutputBinding (neededInput , neededInput ));
380393 }
381394 }
382395 return outputBindings ;
383396 }
384397
398+ private void collectOrderRequiredVariables (Order order , Set <String > visibleVariables ,
399+ Set <String > requiredVariables ) {
400+ for (OrderElem orderElem : order .getElements ()) {
401+ collectReferencedVariables (orderElem .getExpr (), visibleVariables , requiredVariables );
402+ }
403+ }
404+
385405 private FilterPartition partitionFilters (List <Filter > filters , Set <String > visibleVariables ) {
386406 if (filters .isEmpty ()) {
387407 return FilterPartition .empty ();
0 commit comments