/// <summary> /// Evaluates the Ask Union /// </summary> /// <param name="context">Evaluation Context</param> /// <returns></returns> public BaseMultiset Evaluate(SparqlEvaluationContext context) { BaseMultiset initialInput = context.InputMultiset; if (this._lhs is Extend || this._rhs is Extend) { initialInput = new IdentityMultiset(); } context.InputMultiset = initialInput; BaseMultiset lhsResult = context.Evaluate(this._lhs);//this._lhs.Evaluate(context); context.CheckTimeout(); if (lhsResult.IsEmpty) { //Only evaluate the RHS if the LHS was empty context.InputMultiset = initialInput; BaseMultiset rhsResult = context.Evaluate(this._rhs);//this._rhs.Evaluate(context); context.CheckTimeout(); context.OutputMultiset = lhsResult.Union(rhsResult); context.CheckTimeout(); context.InputMultiset = context.OutputMultiset; } else { context.OutputMultiset = lhsResult; } return(context.OutputMultiset); }
/// <summary> /// Evaluates the Lazy Union. /// </summary> /// <param name="context">Evaluation Context.</param> /// <returns></returns> public BaseMultiset Evaluate(SparqlEvaluationContext context) { BaseMultiset initialInput = context.InputMultiset; if (_lhs is Extend || _rhs is Extend) { initialInput = new IdentityMultiset(); } context.InputMultiset = initialInput; BaseMultiset lhsResult = context.Evaluate(_lhs); //this._lhs.Evaluate(context); context.CheckTimeout(); if (lhsResult.Count >= _requiredResults || _requiredResults == -1) { // Only evaluate the RHS if the LHS didn't yield sufficient results context.InputMultiset = initialInput; BaseMultiset rhsResult = context.Evaluate(_rhs); //this._rhs.Evaluate(context); context.CheckTimeout(); context.OutputMultiset = lhsResult.Union(rhsResult); context.CheckTimeout(); context.InputMultiset = context.OutputMultiset; } else { context.OutputMultiset = lhsResult; } return(context.OutputMultiset); }
/// <summary> /// Evaluates the Union /// </summary> /// <param name="context"></param> /// <returns></returns> public BaseMultiset Evaluate(SparqlEvaluationContext context) { BaseMultiset initialInput = context.InputMultiset; if (_lhs is Extend || _rhs is Extend) { initialInput = new IdentityMultiset(); } context.InputMultiset = initialInput; BaseMultiset lhsResult = context.Evaluate(_lhs); context.CheckTimeout(); context.InputMultiset = initialInput; BaseMultiset rhsResult = context.Evaluate(_rhs); context.CheckTimeout(); context.OutputMultiset = lhsResult.Union(rhsResult); context.CheckTimeout(); context.InputMultiset = context.OutputMultiset; return(context.OutputMultiset); }
public void SparqlMultisetLeftJoin() { //Create a load of Nodes to use in the tests Graph g = new Graph(); g.NamespaceMap.AddNamespace(String.Empty, new Uri("http://example.org")); IUriNode s1 = g.CreateUriNode(":s1"); IUriNode s2 = g.CreateUriNode(":s2"); IUriNode p1 = g.CreateUriNode(":p1"); IUriNode p2 = g.CreateUriNode(":p2"); IUriNode rdfsLabel = g.CreateUriNode("rdfs:label"); ILiteralNode o1 = g.CreateLiteralNode("Some Text"); ILiteralNode o2 = g.CreateLiteralNode("1", new Uri(XmlSpecsHelper.XmlSchemaDataTypeInteger)); //Create an ID and Null Multiset IdentityMultiset id = new IdentityMultiset(); NullMultiset nullset = new NullMultiset(); //Create and Populate a Multiset Multiset m = new Multiset(); Set s = new Set(); s.Add("s", s1); s.Add("p", p1); s.Add("o", o1); m.Add(s); s = new Set(); s.Add("s", s2); s.Add("p", p2); s.Add("o", o2); m.Add(s); //Create and Populate another Multiset Multiset n = new Multiset(); s = new Set(); s.Add("s", s1); s.Add("label", o1); n.Add(s); //Create and Populate another Multiset Multiset d = new Multiset(); s = new Set(); s.Add("s1", s1); s.Add("p1", p1); s.Add("o1", o1); d.Add(s); s = new Set(); s.Add("s1", s2); s.Add("p1", p2); s.Add("o1", o2); d.Add(s); //Show the Sets Console.WriteLine("LHS"); foreach (Set set in m.Sets) { Console.WriteLine(set.ToString()); } Console.WriteLine(); Console.WriteLine("RHS"); foreach (Set set in n.Sets) { Console.WriteLine(set.ToString()); } Console.WriteLine(); Console.WriteLine("D"); foreach (Set set in d.Sets) { Console.WriteLine(set.ToString()); } Console.WriteLine(); //Try a Join to Identity Console.WriteLine("Join ID-LHS"); BaseMultiset join = id.Join(m); foreach (Set set in join.Sets) { Console.WriteLine(set.ToString()); } Console.WriteLine(); //Try a Join to Identity Console.WriteLine("Join LHS-ID"); join = m.Join(id); foreach (Set set in join.Sets) { Console.WriteLine(set.ToString()); } Console.WriteLine(); //Try a Join to Null Console.WriteLine("Join NULL-LHS"); join = nullset.Join(m); foreach (Set set in join.Sets) { Console.WriteLine(set.ToString()); } Console.WriteLine(); //Try a Join to Null Console.WriteLine("Join LHS-NULL"); join = m.Join(nullset); foreach (Set set in join.Sets) { Console.WriteLine(set.ToString()); } Console.WriteLine(); //Try a LeftJoin Console.WriteLine("LeftJoin NULL-LHS"); BaseMultiset leftjoin = nullset.LeftJoin(m, new BooleanExpressionTerm(true)); foreach (Set set in leftjoin.Sets) { Console.WriteLine(set.ToString()); } Console.WriteLine(); //Try a LeftJoin Console.WriteLine("LeftJoin LHS-NULL"); leftjoin = m.LeftJoin(nullset, new BooleanExpressionTerm(true)); foreach (Set set in leftjoin.Sets) { Console.WriteLine(set.ToString()); } Console.WriteLine(); //Try a Join Console.WriteLine("Join LHS-RHS"); join = m.Join(n); foreach (Set set in join.Sets) { Console.WriteLine(set.ToString()); } Console.WriteLine(); //Try a LeftOuterJoin Console.WriteLine("LeftJoin LHS-RHS"); leftjoin = m.LeftJoin(n, new BooleanExpressionTerm(true)); foreach (Set set in leftjoin.Sets) { Console.WriteLine(set.ToString()); } Console.WriteLine(); //Try a Produce Console.WriteLine("Product LHS-RHS"); BaseMultiset product = m.Product(n); foreach (Set set in product.Sets) { Console.WriteLine(set.ToString()); } Console.WriteLine(); //Try a Join to Self Console.WriteLine("Product LHS-D"); product = m.Product(d); foreach (Set set in product.Sets) { Console.WriteLine(set.ToString()); } Console.WriteLine(); //Try a Union Console.WriteLine("Union LHS-RHS"); BaseMultiset union = m.Union(n); foreach (Set set in union.Sets) { Console.WriteLine(set.ToString()); } Console.WriteLine(); }
private BaseMultiset StreamingEvaluate(SparqlEvaluationContext context, int pattern, out bool halt) { halt = false; //Handle Empty BGPs if (pattern == 0 && this._triplePatterns.Count == 0) { context.OutputMultiset = new IdentityMultiset(); return(context.OutputMultiset); } BaseMultiset initialInput, localOutput, results = null; //Determine whether the Pattern modifies the existing Input rather than joining to it bool modifies = (this._triplePatterns[pattern] is FilterPattern); bool extended = (pattern > 0 && this._triplePatterns[pattern - 1] is BindPattern); bool modified = (pattern > 0 && this._triplePatterns[pattern - 1] is FilterPattern); //Set up the Input and Output Multiset appropriately switch (pattern) { case 0: //Input is as given and Output is new empty multiset if (!modifies) { initialInput = context.InputMultiset; } else { //If the Pattern will modify the Input and is the first thing in the BGP then it actually modifies a new empty input //This takes care of FILTERs being out of scope initialInput = new Multiset(); } localOutput = new Multiset(); break; case 1: //Input becomes current Output and Output is new empty multiset initialInput = context.OutputMultiset; localOutput = new Multiset(); break; default: if (!extended && !modified) { //Input is join of previous input and output and Output is new empty multiset if (context.InputMultiset.IsDisjointWith(context.OutputMultiset)) { //Disjoint so do a Product initialInput = context.InputMultiset.ProductWithTimeout(context.OutputMultiset, context.RemainingTimeout); } else { //Normal Join initialInput = context.InputMultiset.Join(context.OutputMultiset); } } else { initialInput = context.OutputMultiset; } localOutput = new Multiset(); break; } context.InputMultiset = initialInput; context.OutputMultiset = localOutput; //Get the Triple Pattern we're evaluating ITriplePattern temp = this._triplePatterns[pattern]; int resultsFound = 0; int prevResults = -1; if (temp is TriplePattern) { //Find the first Triple which matches the Pattern TriplePattern tp = (TriplePattern)temp; IEnumerable <Triple> ts = tp.GetTriples(context); //In the case that we're lazily evaluating an optimisable ORDER BY then //we need to apply OrderBy()'s to our enumeration //This only applies to the 1st pattern if (pattern == 0) { if (context.Query != null) { if (context.Query.OrderBy != null && context.Query.IsOptimisableOrderBy) { IComparer <Triple> comparer = context.Query.OrderBy.GetComparer(tp); if (comparer != null) { ts = ts.OrderBy(t => t, comparer); } else { //Can't get a comparer so can't optimise this._requiredResults = -1; } } } } foreach (Triple t in ts) { //Remember to check for Timeouts during Lazy Evaluation context.CheckTimeout(); if (tp.Accepts(context, t)) { resultsFound++; if (tp.IndexType == TripleIndexType.NoVariables) { localOutput = new IdentityMultiset(); context.OutputMultiset = localOutput; } else { context.OutputMultiset.Add(tp.CreateResult(t)); } //Recurse unless we're the last pattern if (pattern < this._triplePatterns.Count - 1) { results = this.StreamingEvaluate(context, pattern + 1, out halt); //If recursion leads to a halt then we halt and return immediately if (halt && results.Count >= this._requiredResults && this._requiredResults != -1) { return(results); } else if (halt) { if (results.Count == 0) { //If recursing leads to no results then eliminate all outputs //Also reset to prevResults to -1 resultsFound = 0; localOutput = new Multiset(); prevResults = -1; } else if (prevResults > -1) { if (results.Count == prevResults) { //If the amount of results found hasn't increased then this match does not //generate any further solutions further down the recursion so we can eliminate //this from the results localOutput.Remove(localOutput.SetIDs.Max()); } } prevResults = results.Count; //If we're supposed to halt but not reached the number of required results then continue context.InputMultiset = initialInput; context.OutputMultiset = localOutput; } else { //Otherwise we need to keep going here //So must reset our input and outputs before continuing context.InputMultiset = initialInput; context.OutputMultiset = new Multiset(); resultsFound--; } } else { //If we're at the last pattern and we've found a match then we can halt halt = true; //Generate the final output and return it if (context.InputMultiset.IsDisjointWith(context.OutputMultiset)) { //Disjoint so do a Product results = context.InputMultiset.ProductWithTimeout(context.OutputMultiset, context.RemainingTimeout); } else { //Normal Join results = context.InputMultiset.Join(context.OutputMultiset); } //If not reached required number of results continue if (results.Count >= this._requiredResults && this._requiredResults != -1) { context.OutputMultiset = results; return(context.OutputMultiset); } } } } } else if (temp is FilterPattern) { FilterPattern filter = (FilterPattern)temp; ISparqlExpression filterExpr = filter.Filter.Expression; if (filter.Variables.IsDisjoint(context.InputMultiset.Variables)) { //Remember to check for Timeouts during Lazy Evaluation context.CheckTimeout(); //Filter is Disjoint so determine whether it has any affect or not if (filter.Variables.Any()) { //Has Variables but disjoint from input => not in scope so gets ignored //Do we recurse or not? if (pattern < this._triplePatterns.Count - 1) { //Recurse and return results = this.StreamingEvaluate(context, pattern + 1, out halt); return(results); } else { //We don't affect the input in any way so just return it return(context.InputMultiset); } } else { //No Variables so have to evaluate it to see if it gives true otherwise try { if (filterExpr.EffectiveBooleanValue(context, 0)) { if (pattern < this._triplePatterns.Count - 1) { //Recurse and return results = this.StreamingEvaluate(context, pattern + 1, out halt); return(results); } else { //Last Pattern and we evaluate to true so can return the input as-is halt = true; return(context.InputMultiset); } } } catch (RdfQueryException) { //Evaluates to false so eliminates all solutions (use an empty Multiset) return(new Multiset()); } } } else { //Remember to check for Timeouts during Lazy Evaluation context.CheckTimeout(); //Test each solution found so far against the Filter and eliminate those that evalute to false/error foreach (int id in context.InputMultiset.SetIDs.ToList()) { try { if (filterExpr.EffectiveBooleanValue(context, id)) { //If evaluates to true then add to output context.OutputMultiset.Add(context.InputMultiset[id]); } } catch (RdfQueryException) { //Error means we ignore the solution } } //Remember to check for Timeouts during Lazy Evaluation context.CheckTimeout(); //Decide whether to recurse or not resultsFound = context.OutputMultiset.Count; if (pattern < this._triplePatterns.Count - 1) { //Recurse then return //We can never decide whether to recurse again at this point as we are not capable of deciding //which solutions should be dumped (that is the job of an earlier pattern in the BGP) results = this.StreamingEvaluate(context, pattern + 1, out halt); return(results); } else { halt = true; //However many results we need we'll halt - previous patterns can call us again if they find more potential solutions //for us to filter return(context.OutputMultiset); } } } else if (temp is BindPattern) { BindPattern bind = (BindPattern)temp; ISparqlExpression bindExpr = bind.AssignExpression; String bindVar = bind.VariableName; if (context.InputMultiset.ContainsVariable(bindVar)) { throw new RdfQueryException("Cannot use a BIND assigment to BIND to a variable that has previously been used in the Query"); } else { //Remember to check for Timeouts during Lazy Evaluation context.CheckTimeout(); //Compute the Binding for every value context.OutputMultiset.AddVariable(bindVar); foreach (ISet s in context.InputMultiset.Sets) { ISet x = s.Copy(); try { INode val = bindExpr.Value(context, s.ID); x.Add(bindVar, val); } catch (RdfQueryException) { //Equivalent to no assignment but the solution is preserved } context.OutputMultiset.Add(x); } //Remember to check for Timeouts during Lazy Evaluation context.CheckTimeout(); //Decide whether to recurse or not resultsFound = context.OutputMultiset.Count; if (pattern < this._triplePatterns.Count - 1) { //Recurse then return results = this.StreamingEvaluate(context, pattern + 1, out halt); return(results); } else { halt = true; //However many results we need we'll halt - previous patterns can call us again if they find more potential solutions //for us to extend return(context.OutputMultiset); } } } else { throw new RdfQueryException("Encountered a " + temp.GetType().FullName + " which is not a lazily evaluable Pattern"); } //If we found no possibles we return the null multiset if (resultsFound == 0) { return(new NullMultiset()); } else { //Generate the final output and return it if (!modifies) { if (context.InputMultiset.IsDisjointWith(context.OutputMultiset)) { //Disjoint so do a Product results = context.InputMultiset.ProductWithTimeout(context.OutputMultiset, context.RemainingTimeout); } else { //Normal Join results = context.InputMultiset.Join(context.OutputMultiset); } context.OutputMultiset = results; } return(context.OutputMultiset); } }
/// <summary> /// Evaluates the Ask Union /// </summary> /// <param name="context">Evaluation Context</param> /// <returns></returns> public BaseMultiset Evaluate(SparqlEvaluationContext context) { BaseMultiset initialInput = context.InputMultiset; if (this._lhs is Extend || this._rhs is Extend) initialInput = new IdentityMultiset(); context.InputMultiset = initialInput; BaseMultiset lhsResult = context.Evaluate(this._lhs);//this._lhs.Evaluate(context); context.CheckTimeout(); if (lhsResult.IsEmpty) { //Only evaluate the RHS if the LHS was empty context.InputMultiset = initialInput; BaseMultiset rhsResult = context.Evaluate(this._rhs);//this._rhs.Evaluate(context); context.CheckTimeout(); context.OutputMultiset = lhsResult.Union(rhsResult); context.CheckTimeout(); context.InputMultiset = context.OutputMultiset; } else { context.OutputMultiset = lhsResult; } return context.OutputMultiset; }
/// <summary> /// Evaluates the Union /// </summary> /// <param name="context"></param> /// <returns></returns> public BaseMultiset Evaluate(SparqlEvaluationContext context) { BaseMultiset initialInput = context.InputMultiset; if (this._lhs is Extend || this._rhs is Extend) initialInput = new IdentityMultiset(); context.InputMultiset = initialInput; BaseMultiset lhsResult = context.Evaluate(this._lhs);//this._lhs.Evaluate(context); context.CheckTimeout(); context.InputMultiset = initialInput; BaseMultiset rhsResult = context.Evaluate(this._rhs);//this._rhs.Evaluate(context); context.CheckTimeout(); context.OutputMultiset = lhsResult.Union(rhsResult); context.CheckTimeout(); context.InputMultiset = context.OutputMultiset; return context.OutputMultiset; }
/// <summary> /// Evaluates the Lazy Union /// </summary> /// <param name="context">Evaluation Context</param> /// <returns></returns> public BaseMultiset Evaluate(SparqlEvaluationContext context) { BaseMultiset initialInput = context.InputMultiset; if (this._lhs is Extend || this._rhs is Extend) initialInput = new IdentityMultiset(); context.InputMultiset = initialInput; BaseMultiset lhsResult = context.Evaluate(this._lhs);//this._lhs.Evaluate(context); context.CheckTimeout(); if (lhsResult.Count >= this._requiredResults || this._requiredResults == -1) { //Only evaluate the RHS if the LHS didn't yield sufficient results context.InputMultiset = initialInput; BaseMultiset rhsResult = context.Evaluate(this._rhs);//this._rhs.Evaluate(context); context.CheckTimeout(); context.OutputMultiset = lhsResult.Union(rhsResult); context.CheckTimeout(); context.InputMultiset = context.OutputMultiset; } else { context.OutputMultiset = lhsResult; } return context.OutputMultiset; }
private BaseMultiset StreamingEvaluate(SparqlEvaluationContext context, int pattern, out bool halt) { halt = false; //Handle Empty BGPs if (pattern == 0 && this._triplePatterns.Count == 0) { context.OutputMultiset = new IdentityMultiset(); return context.OutputMultiset; } BaseMultiset initialInput, localOutput, results = null; //Determine whether the Pattern modifies the existing Input rather than joining to it bool modifies = (this._triplePatterns[pattern] is FilterPattern); bool extended = (pattern > 0 && this._triplePatterns[pattern-1] is BindPattern); bool modified = (pattern > 0 && this._triplePatterns[pattern-1] is FilterPattern); //Set up the Input and Output Multiset appropriately switch (pattern) { case 0: //Input is as given and Output is new empty multiset if (!modifies) { initialInput = context.InputMultiset; } else { //If the Pattern will modify the Input and is the first thing in the BGP then it actually modifies a new empty input //This takes care of FILTERs being out of scope initialInput = new Multiset(); } localOutput = new Multiset(); break; case 1: //Input becomes current Output and Output is new empty multiset initialInput = context.OutputMultiset; localOutput = new Multiset(); break; default: if (!extended && !modified) { //Input is join of previous input and output and Output is new empty multiset if (context.InputMultiset.IsDisjointWith(context.OutputMultiset)) { //Disjoint so do a Product initialInput = context.InputMultiset.ProductWithTimeout(context.OutputMultiset, context.RemainingTimeout); } else { //Normal Join initialInput = context.InputMultiset.Join(context.OutputMultiset); } } else { initialInput = context.OutputMultiset; } localOutput = new Multiset(); break; } context.InputMultiset = initialInput; context.OutputMultiset = localOutput; //Get the Triple Pattern we're evaluating ITriplePattern temp = this._triplePatterns[pattern]; int resultsFound = 0; int prevResults = -1; if (temp is TriplePattern) { //Find the first Triple which matches the Pattern TriplePattern tp = (TriplePattern)temp; IEnumerable<Triple> ts = tp.GetTriples(context); //In the case that we're lazily evaluating an optimisable ORDER BY then //we need to apply OrderBy()'s to our enumeration //This only applies to the 1st pattern if (pattern == 0) { if (context.Query != null) { if (context.Query.OrderBy != null && context.Query.IsOptimisableOrderBy) { IComparer<Triple> comparer = context.Query.OrderBy.GetComparer(tp); if (comparer != null) { ts = ts.OrderBy(t => t, comparer); } else { //Can't get a comparer so can't optimise this._requiredResults = -1; } } } } foreach (Triple t in ts) { //Remember to check for Timeouts during Lazy Evaluation context.CheckTimeout(); if (tp.Accepts(context, t)) { resultsFound++; if (tp.IndexType == TripleIndexType.NoVariables) { localOutput = new IdentityMultiset(); context.OutputMultiset = localOutput; } else { context.OutputMultiset.Add(tp.CreateResult(t)); } //Recurse unless we're the last pattern if (pattern < this._triplePatterns.Count - 1) { results = this.StreamingEvaluate(context, pattern + 1, out halt); //If recursion leads to a halt then we halt and return immediately if (halt && results.Count >= this._requiredResults && this._requiredResults != -1) { return results; } else if (halt) { if (results.Count == 0) { //If recursing leads to no results then eliminate all outputs //Also reset to prevResults to -1 resultsFound = 0; localOutput = new Multiset(); prevResults = -1; } else if (prevResults > -1) { if (results.Count == prevResults) { //If the amount of results found hasn't increased then this match does not //generate any further solutions further down the recursion so we can eliminate //this from the results localOutput.Remove(localOutput.SetIDs.Max()); } } prevResults = results.Count; //If we're supposed to halt but not reached the number of required results then continue context.InputMultiset = initialInput; context.OutputMultiset = localOutput; } else { //Otherwise we need to keep going here //So must reset our input and outputs before continuing context.InputMultiset = initialInput; context.OutputMultiset = new Multiset(); resultsFound--; } } else { //If we're at the last pattern and we've found a match then we can halt halt = true; //Generate the final output and return it if (context.InputMultiset.IsDisjointWith(context.OutputMultiset)) { //Disjoint so do a Product results = context.InputMultiset.ProductWithTimeout(context.OutputMultiset, context.RemainingTimeout); } else { //Normal Join results = context.InputMultiset.Join(context.OutputMultiset); } //If not reached required number of results continue if (results.Count >= this._requiredResults && this._requiredResults != -1) { context.OutputMultiset = results; return context.OutputMultiset; } } } } } else if (temp is FilterPattern) { FilterPattern filter = (FilterPattern)temp; ISparqlExpression filterExpr = filter.Filter.Expression; if (filter.Variables.IsDisjoint(context.InputMultiset.Variables)) { //Remember to check for Timeouts during Lazy Evaluation context.CheckTimeout(); //Filter is Disjoint so determine whether it has any affect or not if (filter.Variables.Any()) { //Has Variables but disjoint from input => not in scope so gets ignored //Do we recurse or not? if (pattern < this._triplePatterns.Count - 1) { //Recurse and return results = this.StreamingEvaluate(context, pattern + 1, out halt); return results; } else { //We don't affect the input in any way so just return it return context.InputMultiset; } } else { //No Variables so have to evaluate it to see if it gives true otherwise try { if (filterExpr.Evaluate(context, 0).AsSafeBoolean()) { if (pattern < this._triplePatterns.Count - 1) { //Recurse and return results = this.StreamingEvaluate(context, pattern + 1, out halt); return results; } else { //Last Pattern and we evaluate to true so can return the input as-is halt = true; return context.InputMultiset; } } } catch (RdfQueryException) { //Evaluates to false so eliminates all solutions (use an empty Multiset) return new Multiset(); } } } else { //Remember to check for Timeouts during Lazy Evaluation context.CheckTimeout(); //Test each solution found so far against the Filter and eliminate those that evalute to false/error foreach (int id in context.InputMultiset.SetIDs.ToList()) { try { if (filterExpr.Evaluate(context, id).AsSafeBoolean()) { //If evaluates to true then add to output context.OutputMultiset.Add(context.InputMultiset[id].Copy()); } } catch (RdfQueryException) { //Error means we ignore the solution } } //Remember to check for Timeouts during Lazy Evaluation context.CheckTimeout(); //Decide whether to recurse or not resultsFound = context.OutputMultiset.Count; if (pattern < this._triplePatterns.Count - 1) { //Recurse then return //We can never decide whether to recurse again at this point as we are not capable of deciding //which solutions should be dumped (that is the job of an earlier pattern in the BGP) results = this.StreamingEvaluate(context, pattern + 1, out halt); return results; } else { halt = true; //However many results we need we'll halt - previous patterns can call us again if they find more potential solutions //for us to filter return context.OutputMultiset; } } } else if (temp is BindPattern) { BindPattern bind = (BindPattern)temp; ISparqlExpression bindExpr = bind.AssignExpression; String bindVar = bind.VariableName; if (context.InputMultiset.ContainsVariable(bindVar)) { throw new RdfQueryException("Cannot use a BIND assigment to BIND to a variable that has previously been used in the Query"); } else { //Remember to check for Timeouts during Lazy Evaluation context.CheckTimeout(); //Compute the Binding for every value context.OutputMultiset.AddVariable(bindVar); foreach (ISet s in context.InputMultiset.Sets) { ISet x = s.Copy(); try { INode val = bindExpr.Evaluate(context, s.ID); x.Add(bindVar, val); } catch (RdfQueryException) { //Equivalent to no assignment but the solution is preserved } context.OutputMultiset.Add(x.Copy()); } //Remember to check for Timeouts during Lazy Evaluation context.CheckTimeout(); //Decide whether to recurse or not resultsFound = context.OutputMultiset.Count; if (pattern < this._triplePatterns.Count - 1) { //Recurse then return results = this.StreamingEvaluate(context, pattern + 1, out halt); return results; } else { halt = true; //However many results we need we'll halt - previous patterns can call us again if they find more potential solutions //for us to extend return context.OutputMultiset; } } } else { throw new RdfQueryException("Encountered a " + temp.GetType().FullName + " which is not a lazily evaluable Pattern"); } //If we found no possibles we return the null multiset if (resultsFound == 0) { return new NullMultiset(); } else { //Generate the final output and return it if (!modifies) { if (context.InputMultiset.IsDisjointWith(context.OutputMultiset)) { //Disjoint so do a Product results = context.InputMultiset.ProductWithTimeout(context.OutputMultiset, context.RemainingTimeout); } else { //Normal Join results = context.InputMultiset.Join(context.OutputMultiset); } context.OutputMultiset = results; } return context.OutputMultiset; } }