Skip to content

Commit 20114d4

Browse files
GH-4769 Use retain set logic to hide variables out of scope for a filter
Signed-off-by: Jerven Bolleman <jerven.bolleman@sib.swiss>
1 parent 06d817c commit 20114d4

1 file changed

Lines changed: 17 additions & 188 deletions

File tree

  • core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator

core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/FilterIterator.java

Lines changed: 17 additions & 188 deletions
Original file line numberDiff line numberDiff line change
@@ -39,26 +39,25 @@ public class FilterIterator extends FilterIteration<BindingSet, QueryEvaluationE
3939
private final EvaluationStrategy strategy;
4040
private final Function<BindingSet, BindingSet> retain;
4141

42-
public static QueryEvaluationStep supply(Filter node, EvaluationStrategy strategy,
42+
public static QueryEvaluationStep supply(Filter filter, EvaluationStrategy strategy,
4343
QueryEvaluationContext context) {
44-
QueryEvaluationStep arg = strategy.precompile(node.getArg(), context);
44+
QueryEvaluationStep arg = strategy.precompile(filter.getArg(), context);
4545
QueryValueEvaluationStep ves;
4646
try {
47-
// final QueryEvaluationContext context2 = new FilterIterator.RetainedVariableFilteredQueryEvaluationContext(
48-
// node, context);
49-
ves = strategy.precompile(node.getCondition(), context);
47+
ves = strategy.precompile(filter.getCondition(), context);
5048
} catch (QueryEvaluationException e) {
5149
// If we have a failed compilation we always return false.
5250
// Which means empty. so let's short circuit that.
5351
return QueryEvaluationStep.EMPTY;
5452
}
55-
return new QueryEvaluationStep() {
53+
Function<BindingSet, BindingSet> retain;
54+
if (!isPartOfSubQuery(filter)) {
55+
retain = buildRetainFunction(filter, context);
56+
} else {
57+
retain = Function.identity();
58+
}
5659

57-
@Override
58-
public CloseableIteration<BindingSet, QueryEvaluationException> evaluate(BindingSet bs) {
59-
return new FilterIterator(node, arg.evaluate(bs), ves, strategy, context);
60-
}
61-
};
60+
return (bs) -> new FilterIterator(arg.evaluate(bs), ves, strategy, retain);
6261
}
6362

6463
/*--------------*
@@ -74,35 +73,27 @@ public FilterIterator(Filter filter, CloseableIteration<BindingSet, QueryEvaluat
7473
this.retain = (bs) -> {
7574
QueryBindingSet nbs = new QueryBindingSet(bs);
7675
nbs.retainAll(filter.getBindingNames());
77-
return bs;
76+
return nbs;
7877
};
7978
} else {
8079
this.retain = Function.identity();
8180
}
8281
}
8382

84-
private FilterIterator(Filter filter, CloseableIteration<BindingSet, QueryEvaluationException> iter,
85-
QueryValueEvaluationStep condition, EvaluationStrategy strategy, QueryEvaluationContext context)
83+
private FilterIterator(CloseableIteration<BindingSet, QueryEvaluationException> iter,
84+
QueryValueEvaluationStep condition, EvaluationStrategy strategy, Function<BindingSet, BindingSet> retain)
8685
throws QueryEvaluationException {
8786
super(iter);
8887
this.condition = condition;
8988
this.strategy = strategy;
9089
// FIXME Jeen Boekstra scopeBindingNames should include bindings from superquery
9190
// if the filter is part of a subquery. This is a workaround: we should fix the
9291
// settings of scopeBindingNames, rather than skipping the limiting of bindings.
93-
if (!isPartOfSubQuery(filter)) {
94-
// this.retain = (bs) -> {
95-
// QueryBindingSet nbs = new QueryBindingSet(bs);
96-
// nbs.retainAll(filter.getBindingNames());
97-
// return bs;
98-
// };
99-
this.retain = buildRetainFunction(filter, context);
100-
} else {
101-
this.retain = Function.identity();
102-
}
92+
this.retain = retain;
93+
10394
}
10495

105-
private Function<BindingSet, BindingSet> buildRetainFunction(Filter filter, QueryEvaluationContext context) {
96+
private static Function<BindingSet, BindingSet> buildRetainFunction(Filter filter, QueryEvaluationContext context) {
10697
final Set<String> bindingNames = filter.getBindingNames();
10798
@SuppressWarnings("unchecked")
10899
final Predicate<BindingSet>[] hasBinding = new Predicate[bindingNames.size()];
@@ -111,7 +102,7 @@ private Function<BindingSet, BindingSet> buildRetainFunction(Filter filter, Quer
111102
Iterator<String> bi = bindingNames.iterator();
112103
for (int i = 0; bi.hasNext(); i++) {
113104
String bindingName = bi.next();
114-
hasBinding[i] = (bs) -> bs.hasBinding(bindingName);
105+
hasBinding[i] = context.hasBinding(bindingName);
115106
final Function<BindingSet, Value> getValue = context.getValue(bindingName);
116107
// Can't use this as there might be bindingNames that the filter expects that are not available.
117108
// See line the meet(Var) in the ArrayBindingSet.findAllVariablesUsedInQuery(QueryRoot method)
@@ -142,7 +133,6 @@ protected boolean accept(BindingSet bindings) throws QueryEvaluationException {
142133
}
143134
}
144135

145-
// @Deprecated(forRemoval = true, since = "4.2.1")
146136
public static boolean isPartOfSubQuery(QueryModelNode node) {
147137
if (node instanceof SubQueryValueOperator) {
148138
return true;
@@ -156,165 +146,4 @@ public static boolean isPartOfSubQuery(QueryModelNode node) {
156146
}
157147
}
158148

159-
// protected static class InExistsVarCollector extends AbstractSimpleQueryModelVisitor<QueryEvaluationException> {
160-
// private final VarCollector vc;
161-
//
162-
// public InExistsVarCollector(VarCollector vc) {
163-
// super();
164-
// this.vc = vc;
165-
// }
166-
//
167-
// @Override
168-
// public void meet(Exists ex) {
169-
// ex.visit(vc);
170-
// }
171-
// }
172-
173-
// protected static class VarCollector extends AbstractSimpleQueryModelVisitor<QueryEvaluationException> {
174-
//
175-
// private final Set<String> collectedVars = new HashSet<>();
176-
//
177-
// public VarCollector() {
178-
// super(true);
179-
// }
180-
//
181-
// @Override
182-
// public void meet(Var var) {
183-
// if (!var.isAnonymous()) {
184-
// collectedVars.add(var.getName());
185-
// }
186-
// }
187-
//
188-
// @Override
189-
// public void meet(BindingSetAssignment node) throws QueryEvaluationException {
190-
// for (BindingSet bs : node.getBindingSets()) {
191-
// for (String name : bs.getBindingNames()) {
192-
// collectedVars.add(name);
193-
// }
194-
// }
195-
// super.meet(node);
196-
// }
197-
//
198-
// /**
199-
// * @return Returns the collectedVars.
200-
// */
201-
// public Set<String> getCollectedVars() {
202-
// return collectedVars;
203-
// }
204-
//
205-
// @Override
206-
// public void meetUnaryTupleOperator(UnaryTupleOperator node) {
207-
// if (!node.isVariableScopeChange()) {
208-
// super.meetUnaryTupleOperator(node);
209-
// }
210-
// }
211-
//
212-
// @Override
213-
// public void meetBinaryTupleOperator(BinaryTupleOperator node) {
214-
// if (!node.isVariableScopeChange()) {
215-
// super.meetBinaryTupleOperator(node);
216-
// }
217-
// }
218-
//
219-
// @Override
220-
// protected void meetBinaryValueOperator(BinaryValueOperator node) throws RuntimeException {
221-
// if (!node.isVariableScopeChange()) {
222-
// super.meetBinaryValueOperator(node);
223-
// }
224-
// }
225-
//
226-
// @Override
227-
// protected void meetNAryValueOperator(NAryValueOperator node) throws RuntimeException {
228-
// if (!node.isVariableScopeChange()) {
229-
// super.meetNAryValueOperator(node);
230-
// }
231-
// }
232-
//
233-
// @Override
234-
// protected void meetSubQueryValueOperator(SubQueryValueOperator node) throws RuntimeException {
235-
// if (!node.isVariableScopeChange()) {
236-
// super.meetSubQueryValueOperator(node);
237-
// }
238-
// }
239-
//
240-
// @Override
241-
// protected void meetUnaryValueOperator(UnaryValueOperator node) throws RuntimeException {
242-
// if (!node.isVariableScopeChange()) {
243-
// super.meetUnaryValueOperator(node);
244-
// }
245-
// }
246-
// }
247-
248-
// /**
249-
// * This is used to make sure that no variable is seen by the filter that are not in scope. Historically important in
250-
// * subquery cases. See also GH-4769
251-
// */
252-
// public static final class RetainedVariableFilteredQueryEvaluationContext implements QueryEvaluationContext {
253-
// private final QueryEvaluationContext context;
254-
// private final Set<String> inScopeVariableNames;
255-
//
256-
//// private final Filter node;
257-
// public RetainedVariableFilteredQueryEvaluationContext(Filter node, QueryEvaluationContext contextToFilter) {
258-
// this.context = contextToFilter;
259-
//
260-
//// this.node = node;
261-
// }
262-
//
263-
// @Override
264-
// public Literal getNow() {
265-
// return context.getNow();
266-
// }
267-
//
268-
// @Override
269-
// public Dataset getDataset() {
270-
// return context.getDataset();
271-
// }
272-
//
273-
// @Override
274-
// public Predicate<BindingSet> hasBinding(String variableName) {
275-
// if (isVariableInScope(variableName)) {
276-
// return context.hasBinding(variableName);
277-
// } else {
278-
// return (bs) -> false;
279-
// }
280-
// }
281-
//
282-
// boolean isVariableInScope(String variableName) {
283-
// return inScopeVariableNames.contains(variableName);
284-
// }
285-
//
286-
// @Override
287-
// public java.util.function.Function<BindingSet, Binding> getBinding(String variableName) {
288-
// if (isVariableInScope(variableName)) {
289-
// return context.getBinding(variableName);
290-
// } else {
291-
// return (bs) -> null;
292-
// }
293-
// }
294-
//
295-
// @Override
296-
// public java.util.function.Function<BindingSet, Value> getValue(String variableName) {
297-
// if (isVariableInScope(variableName)) {
298-
// return context.getValue(variableName);
299-
// } else {
300-
// return (bs) -> null;
301-
// }
302-
// }
303-
//
304-
// @Override
305-
// public BiConsumer<Value, MutableBindingSet> setBinding(String variableName) {
306-
// return context.setBinding(variableName);
307-
// }
308-
//
309-
// @Override
310-
// public MutableBindingSet createBindingSet() {
311-
// return context.createBindingSet();
312-
// }
313-
//
314-
// @Override
315-
// public BiConsumer<Value, MutableBindingSet> addBinding(String variableName) {
316-
// return context.addBinding(variableName);
317-
// }
318-
// }
319-
320149
}

0 commit comments

Comments
 (0)