1111// Some portions generated by Codex
1212package org .eclipse .rdf4j .query .algebra .evaluation .optimizer ;
1313
14- import java .util .Collection ;
1514import java .util .Set ;
1615
1716import org .eclipse .rdf4j .query .BindingSet ;
1817import org .eclipse .rdf4j .query .Dataset ;
1918import org .eclipse .rdf4j .query .algebra .BindingSetAssignment ;
19+ import org .eclipse .rdf4j .query .algebra .Filter ;
2020import org .eclipse .rdf4j .query .algebra .Join ;
2121import org .eclipse .rdf4j .query .algebra .StatementPattern ;
2222import org .eclipse .rdf4j .query .algebra .TupleExpr ;
2323import org .eclipse .rdf4j .query .algebra .Var ;
2424import org .eclipse .rdf4j .query .algebra .evaluation .QueryOptimizer ;
2525import org .eclipse .rdf4j .query .algebra .helpers .AbstractSimpleQueryModelVisitor ;
26+ import org .eclipse .rdf4j .query .algebra .helpers .collectors .VarNameCollector ;
2627
2728/**
28- * Reorders joins to avoid an early cartesian product between two {@link BindingSetAssignment}s (VALUES) when the result
29- * is immediately joined with a {@link StatementPattern} that can be evaluated efficiently with a single bound side .
29+ * Rewrites specific VALUES cross-products so the {@link StatementPattern} is evaluated with both sides bound without
30+ * materializing an explicit cartesian join between two {@link BindingSetAssignment}s .
3031 */
3132public class BindingSetAssignmentJoinOrderOptimizer implements QueryOptimizer {
3233
@@ -42,28 +43,26 @@ private static final class BindingSetAssignmentJoinOrderVisitor
4243 extends AbstractSimpleQueryModelVisitor <RuntimeException > {
4344
4445 @ Override
45- public void meet (Join join ) throws RuntimeException {
46- super .meet (join );
47-
48- StatementPattern statementPattern ;
49- Join bindingSetJoin ;
50- if (join .getLeftArg () instanceof Join && join .getRightArg () instanceof StatementPattern ) {
51- bindingSetJoin = (Join ) join .getLeftArg ();
52- statementPattern = (StatementPattern ) join .getRightArg ();
53- } else if (join .getRightArg () instanceof Join && join .getLeftArg () instanceof StatementPattern ) {
54- bindingSetJoin = (Join ) join .getRightArg ();
55- statementPattern = (StatementPattern ) join .getLeftArg ();
56- } else {
46+ public void meet (Filter filter ) throws RuntimeException {
47+ super .meet (filter );
48+
49+ if (!(filter .getArg () instanceof Join )) {
50+ return ;
51+ }
52+
53+ Join join = (Join ) filter .getArg ();
54+ StatementPattern statementPattern = statementPattern (join );
55+ if (statementPattern == null ) {
5756 return ;
5857 }
5958
60- if (!( bindingSetJoin . getLeftArg () instanceof BindingSetAssignment )
61- || !( bindingSetJoin . getRightArg () instanceof BindingSetAssignment ) ) {
59+ Join valuesJoin = valuesJoin ( join );
60+ if ( valuesJoin == null ) {
6261 return ;
6362 }
6463
65- BindingSetAssignment leftValues = (BindingSetAssignment ) bindingSetJoin .getLeftArg ();
66- BindingSetAssignment rightValues = (BindingSetAssignment ) bindingSetJoin .getRightArg ();
64+ BindingSetAssignment leftValues = (BindingSetAssignment ) valuesJoin .getLeftArg ();
65+ BindingSetAssignment rightValues = (BindingSetAssignment ) valuesJoin .getRightArg ();
6766 if (!areDisjoint (leftValues .getBindingNames (), rightValues .getBindingNames ())) {
6867 return ;
6968 }
@@ -73,17 +72,53 @@ public void meet(Join join) throws RuntimeException {
7372 return ;
7473 }
7574
76- BindingSetAssignment firstValues = chooseFirst (statementPattern , leftValues , rightValues );
77- BindingSetAssignment secondValues = firstValues == leftValues ? rightValues : leftValues ;
75+ Set <String > filterVars = VarNameCollector .process (filter .getCondition ());
76+ if (!join .getBindingNames ().containsAll (filterVars )) {
77+ return ;
78+ }
7879
79- StatementPattern statementPatternClone = statementPattern .clone ();
80- Join inner = new Join ((TupleExpr ) firstValues .clone (), statementPatternClone );
81- Join outer = new Join (inner , (TupleExpr ) secondValues .clone ());
80+ BindingSetAssignment subjectValues = subjectValues (statementPattern , leftValues , rightValues );
81+ if (subjectValues == null ) {
82+ return ;
83+ }
84+ BindingSetAssignment objectValues = subjectValues == leftValues ? rightValues : leftValues ;
8285
83- join .replaceWith (outer );
86+ Filter statementPatternFilter = new Filter (statementPattern .clone (), filter .getCondition ().clone ());
87+ Join inner = new Join ((TupleExpr ) objectValues .clone (), statementPatternFilter );
88+ Join outer = new Join ((TupleExpr ) subjectValues .clone (), inner );
89+
90+ filter .replaceWith (outer );
8491 outer .visit (this );
8592 }
8693
94+ private static StatementPattern statementPattern (Join join ) {
95+ if (join .getLeftArg () instanceof StatementPattern ) {
96+ return (StatementPattern ) join .getLeftArg ();
97+ }
98+ if (join .getRightArg () instanceof StatementPattern ) {
99+ return (StatementPattern ) join .getRightArg ();
100+ }
101+ return null ;
102+ }
103+
104+ private static Join valuesJoin (Join join ) {
105+ if (join .getLeftArg () instanceof Join ) {
106+ Join candidate = (Join ) join .getLeftArg ();
107+ if (candidate .getLeftArg () instanceof BindingSetAssignment
108+ && candidate .getRightArg () instanceof BindingSetAssignment ) {
109+ return candidate ;
110+ }
111+ }
112+ if (join .getRightArg () instanceof Join ) {
113+ Join candidate = (Join ) join .getRightArg ();
114+ if (candidate .getLeftArg () instanceof BindingSetAssignment
115+ && candidate .getRightArg () instanceof BindingSetAssignment ) {
116+ return candidate ;
117+ }
118+ }
119+ return null ;
120+ }
121+
87122 private static boolean areDisjoint (Set <String > left , Set <String > right ) {
88123 for (String name : left ) {
89124 if (right .contains (name )) {
@@ -106,49 +141,20 @@ private static boolean statementPatternUsesAny(StatementPattern statementPattern
106141 return false ;
107142 }
108143
109- private static BindingSetAssignment chooseFirst (StatementPattern statementPattern , BindingSetAssignment left ,
144+ private static BindingSetAssignment subjectValues (StatementPattern statementPattern , BindingSetAssignment left ,
110145 BindingSetAssignment right ) {
111- int leftScore = positionScore (statementPattern , left .getBindingNames ());
112- int rightScore = positionScore (statementPattern , right .getBindingNames ());
113- if (leftScore != rightScore ) {
114- return leftScore < rightScore ? left : right ;
115- }
116-
117- int leftSize = estimateSize (left );
118- int rightSize = estimateSize (right );
119- if (leftSize != rightSize ) {
120- return leftSize <= rightSize ? left : right ;
121- }
122-
123- return left ;
124- }
125-
126- private static int positionScore (StatementPattern statementPattern , Set <String > names ) {
127146 Var subject = statementPattern .getSubjectVar ();
128- if (subject != null && !subject .hasValue () && names .contains (subject .getName ())) {
129- return 0 ;
130- }
131- Var object = statementPattern .getObjectVar ();
132- if (object != null && !object .hasValue () && names .contains (object .getName ())) {
133- return 1 ;
147+ if (subject == null || subject .hasValue ()) {
148+ return null ;
134149 }
135- Var predicate = statementPattern . getPredicateVar ();
136- if (predicate != null && ! predicate . hasValue () && names .contains (predicate . getName () )) {
137- return 2 ;
150+ String subjectName = subject . getName ();
151+ if (left . getBindingNames () .contains (subjectName )) {
152+ return left ;
138153 }
139- Var context = statementPattern .getContextVar ();
140- if (context != null && !context .hasValue () && names .contains (context .getName ())) {
141- return 3 ;
142- }
143- return Integer .MAX_VALUE ;
144- }
145-
146- private static int estimateSize (BindingSetAssignment assignment ) {
147- Iterable <BindingSet > bindingSets = assignment .getBindingSets ();
148- if (bindingSets instanceof Collection <?>) {
149- return ((Collection <?>) bindingSets ).size ();
154+ if (right .getBindingNames ().contains (subjectName )) {
155+ return right ;
150156 }
151- return Integer . MAX_VALUE ;
157+ return null ;
152158 }
153159 }
154160}
0 commit comments