/// <summary> /// Generates a Comparer than can be used to do Ordering based on the given Triple Pattern /// </summary> /// <param name="pattern">Triple Pattern</param> /// <returns></returns> public override IComparer <Triple> GetComparer(IMatchTriplePattern pattern) { if (this._expr is VariableTerm) { IComparer <Triple> child = (this._child == null) ? null : this._child.GetComparer(pattern); Func <Triple, Triple, int> compareFunc = null; String var = this._expr.Variables.First(); if (var.Equals(pattern.Subject.VariableName)) { compareFunc = (x, y) => this._comparer.Compare(x.Subject, y.Subject); } else if (var.Equals(pattern.Predicate.VariableName)) { compareFunc = (x, y) => this._comparer.Compare(x.Predicate, y.Predicate); } else if (var.Equals(pattern.Object.VariableName)) { compareFunc = (x, y) => this._comparer.Compare(x.Object, y.Object); } if (compareFunc == null) { return(null); } return(new TripleComparer(compareFunc, this.Descending, child)); } else { return(null); } }
public void CanCreateTriplePatternsUsingTypedLiteralObject() { // when _builder.Subject("s").Predicate("p").ObjectLiteral(42, new Uri(XmlSpecsHelper.XmlSchemaDataTypeInteger)); // then Assert.Single(_builder.Patterns); IMatchTriplePattern pattern = (IMatchTriplePattern)_builder.Patterns.Single(); Assert.True(pattern.Object is NodeMatchPattern); Assert.Equal("42", ((dynamic)pattern.Object).Node.Value); Assert.Equal(new Uri(XmlSpecsHelper.XmlSchemaDataTypeInteger), ((dynamic)pattern.Object).Node.DataType); }
public void CanCreateTriplePatternsUsingLiteralObjectWithLanuageTag2() { // when _builder.Subject("s").Predicate("p").ObjectLiteral(42, "pl-PL"); // then Assert.Single(_builder.Patterns); IMatchTriplePattern pattern = (IMatchTriplePattern)_builder.Patterns.Single(); Assert.True(pattern.Object is NodeMatchPattern); Assert.Equal("42", ((dynamic)pattern.Object).Node.Value); Assert.Null(((dynamic)pattern.Object).Node.DataType); Assert.Equal("pl-pl", ((dynamic)pattern.Object).Node.Language); }
public void CanCreateTriplePatternsUsingIntegerLiteralObject() { // when _builder.Subject("s").Predicate("p").ObjectLiteral(42); // then Assert.Single(_builder.Patterns); IMatchTriplePattern pattern = (IMatchTriplePattern)_builder.Patterns.Single(); Assert.True(pattern.Object is NodeMatchPattern); Assert.Equal("42", ((dynamic)pattern.Object).Node.Value); Assert.Null(((dynamic)pattern.Object).Node.DataType); Assert.True(string.IsNullOrWhiteSpace(((dynamic)pattern.Object).Node.Language)); }
public void CanCreateTriplePatternsUsingBlankNodeForSubject() { // when _builder.Subject <IBlankNode>("s").Predicate("p").Object("o"); // then Assert.Single(_builder.Patterns); IMatchTriplePattern pattern = (IMatchTriplePattern)_builder.Patterns.Single(); Assert.True(pattern.Subject is BlankNodePattern); Assert.Equal("_:s", ((BlankNodePattern)pattern.Subject).ID); Assert.True(pattern.Predicate is VariablePattern); Assert.Equal("p", pattern.Predicate.VariableName); Assert.True(pattern.Object is VariablePattern); Assert.Equal("o", pattern.Object.VariableName); }
public void CanCreateTriplePatternsUsingUriForObject() { // when _builder.Subject("s").Predicate("p").Object(new Uri("http://xmlns.com/foaf/0.1/Person")); // then Assert.Single(_builder.Patterns); IMatchTriplePattern pattern = (IMatchTriplePattern)_builder.Patterns.Single(); Assert.True(pattern.Predicate is VariablePattern); Assert.Equal("p", pattern.Predicate.VariableName); Assert.True(pattern.Subject is VariablePattern); Assert.Equal("s", pattern.Subject.VariableName); Assert.True(pattern.Object is NodeMatchPattern); Assert.Equal(new Uri("http://xmlns.com/foaf/0.1/Person"), ((dynamic)pattern.Object).Node.Uri); }
public void CanCreateTriplePatternUsingVariableNames() { // when _builder.Subject("s").Predicate("p").Object("o"); // then Assert.Single(_builder.Patterns); IMatchTriplePattern pattern = (IMatchTriplePattern)_builder.Patterns.Single(); Assert.True(pattern.Subject is VariablePattern); Assert.Equal("s", pattern.Subject.VariableName); Assert.True(pattern.Predicate is VariablePattern); Assert.Equal("p", pattern.Predicate.VariableName); Assert.True(pattern.Object is VariablePattern); Assert.Equal("o", pattern.Object.VariableName); }
public void CanCreateTriplePatternsUsingDateTimeLiteralObject() { // given var dateTime = new DateTime(2012, 10, 13, 15, 45, 15); // when _builder.Subject("s").Predicate("p").ObjectLiteral(dateTime); // then Assert.Single(_builder.Patterns); IMatchTriplePattern pattern = (IMatchTriplePattern)_builder.Patterns.Single(); Assert.True(pattern.Object is NodeMatchPattern); Assert.Equal(dateTime.ToString(XmlSpecsHelper.XmlSchemaDateTimeFormat), ((dynamic)pattern.Object).Node.Value); Assert.Null(((dynamic)pattern.Object).Node.DataType); Assert.True(string.IsNullOrWhiteSpace(((dynamic)pattern.Object).Node.Language)); }
public void CanCreateTriplePatternsUsingDateTimeOffsetLiteralObject() { // given var dateTime = new DateTimeOffset(2012, 10, 13, 20, 35, 10, new TimeSpan(0, 1, 30, 0)); // when _builder.Subject("s").Predicate("p").ObjectLiteral(dateTime); // then Assert.Single(_builder.Patterns); IMatchTriplePattern pattern = (IMatchTriplePattern)_builder.Patterns.Single(); Assert.True(pattern.Object is NodeMatchPattern); Assert.Equal("2012-10-13T20:35:10.000000+01:30", ((dynamic)pattern.Object).Node.Value); Assert.Null(((dynamic)pattern.Object).Node.DataType); Assert.True(string.IsNullOrWhiteSpace(((dynamic)pattern.Object).Node.Language)); }
public void CanCreateTriplePatternsUsingActualPatternItems() { // given PatternItem s = new VariablePattern("s"); PatternItem p = new VariablePattern("p"); PatternItem o = new VariablePattern("o"); // when _builder.Subject(s).Predicate(p).Object(o); // then Assert.Single(_builder.Patterns); IMatchTriplePattern pattern = (IMatchTriplePattern)_builder.Patterns.Single(); Assert.Same(s, pattern.Subject); Assert.Same(p, pattern.Predicate); Assert.Same(o, pattern.Object); }
public void CanCreateTriplePatternsUsingINodeForObject() { // given var node = new NodeFactory().CreateUriNode(new Uri("http://www.example.com/object")); // when _builder.Subject("s").Predicate("p").Object(node); // then Assert.Single(_builder.Patterns); IMatchTriplePattern pattern = (IMatchTriplePattern)_builder.Patterns.Single(); Assert.True(pattern.Object is NodeMatchPattern); Assert.Same(node, ((NodeMatchPattern)pattern.Object).Node); Assert.True(pattern.Predicate is VariablePattern); Assert.Equal("p", pattern.Predicate.VariableName); Assert.True(pattern.Subject is VariablePattern); Assert.Equal("s", pattern.Subject.VariableName); }
public void CanCreateTriplePatternsUsingINodeForSubject() { // given var node = new NodeFactory().CreateBlankNode("bnode"); // when _builder.Subject(node).Predicate("p").Object("o"); // then Assert.Single(_builder.Patterns); IMatchTriplePattern pattern = (IMatchTriplePattern)_builder.Patterns.Single(); Assert.True(pattern.Subject is NodeMatchPattern); Assert.Same(node, ((NodeMatchPattern)pattern.Subject).Node); Assert.True(pattern.Predicate is VariablePattern); Assert.Equal("p", pattern.Predicate.VariableName); Assert.True(pattern.Object is VariablePattern); Assert.Equal("o", pattern.Object.VariableName); }
public void CanCreateTriplePatternsUsingIUriNodeForPredicate() { // given var node = new NodeFactory().CreateUriNode(new Uri("http://www.example.com/predicate")); // when _builder.Subject("s").PredicateUri(node).Object("o"); // then Assert.AreEqual(1, _builder.Patterns.Length); IMatchTriplePattern pattern = (IMatchTriplePattern)_builder.Patterns.Single(); Assert.IsTrue(pattern.Subject is VariablePattern); Assert.AreEqual("s", pattern.Subject.VariableName); Assert.IsTrue(pattern.Predicate is NodeMatchPattern); Assert.AreSame(node, ((NodeMatchPattern)pattern.Predicate).Node); Assert.IsTrue(pattern.Object is VariablePattern); Assert.AreEqual("o", pattern.Object.VariableName); }
public void CanCreateTriplePatternsUsingUriForPredicate() { // given var predicateUri = new Uri("http://www.example.com/property"); // when _builder.Subject("s").PredicateUri(predicateUri).Object("o"); // then Assert.Single(_builder.Patterns); IMatchTriplePattern pattern = (IMatchTriplePattern)_builder.Patterns.Single(); Assert.True(pattern.Subject is VariablePattern); Assert.Equal("s", pattern.Subject.VariableName); Assert.True(pattern.Predicate is NodeMatchPattern); Assert.Equal(new Uri("http://www.example.com/property"), ((dynamic)pattern.Predicate).Node.Uri); Assert.True(pattern.Object is VariablePattern); Assert.Equal("o", pattern.Object.VariableName); }
public void CanCreateTriplePatternsUsingQNameForSubject() { // given const string predicateQName = "foaf:name"; _namespaceMapper.Setup(m => m.GetNamespaceUri("foaf")).Returns(new Uri("http://xmlns.com/foaf/0.1/")); // when _builder.Subject <IUriNode>(predicateQName).Predicate("p").Object("o"); // then Assert.Single(_builder.Patterns); IMatchTriplePattern pattern = (IMatchTriplePattern)_builder.Patterns.Single(); Assert.True(pattern.Subject is NodeMatchPattern); Assert.Equal(new Uri("http://xmlns.com/foaf/0.1/name"), ((dynamic)pattern.Subject).Node.Uri); Assert.True(pattern.Predicate is VariablePattern); Assert.Equal("p", pattern.Predicate.VariableName); Assert.True(pattern.Object is VariablePattern); Assert.Equal("o", pattern.Object.VariableName); }
/// <summary> /// Generates a Comparer than can be used to do Ordering based on the given Triple Pattern. /// </summary> /// <param name="pattern">Triple Pattern.</param> /// <returns></returns> public override IComparer <Triple> GetComparer(IMatchTriplePattern pattern) { IComparer <Triple> child = (_child == null) ? null : _child.GetComparer(pattern); Func <Triple, Triple, int> compareFunc = null; if (_varname.Equals(pattern.Subject.VariableName)) { compareFunc = (x, y) => _comparer.Compare(x.Subject, y.Subject); } else if (_varname.Equals(pattern.Predicate.VariableName)) { compareFunc = (x, y) => _comparer.Compare(x.Predicate, y.Predicate); } else if (_varname.Equals(pattern.Object.VariableName)) { compareFunc = (x, y) => _comparer.Compare(x.Object, y.Object); } if (compareFunc == null) { return(null); } return(new TripleComparer(compareFunc, Descending, child)); }
/// <summary> /// Formats a Triple Pattern in nicely formatted SPARQL syntax /// </summary> /// <param name="tp">Triple Pattern</param> /// <returns></returns> public virtual String Format(ITriplePattern tp) { StringBuilder output = new StringBuilder(); switch (tp.PatternType) { case TriplePatternType.Match: IMatchTriplePattern match = (IMatchTriplePattern)tp; output.Append(this.Format(match.Subject, TripleSegment.Subject)); output.Append(' '); output.Append(this.Format(match.Predicate, TripleSegment.Predicate)); output.Append(' '); output.Append(this.Format(match.Object, TripleSegment.Object)); output.Append(" ."); break; case TriplePatternType.Filter: IFilterPattern filter = (IFilterPattern)tp; output.Append("FILTER("); output.Append(this.FormatExpression(filter.Filter.Expression)); output.Append(")"); break; case TriplePatternType.SubQuery: ISubQueryPattern subquery = (ISubQueryPattern)tp; output.AppendLine("{"); output.AppendLineIndented(this.Format(subquery.SubQuery), 2); output.AppendLine("}"); break; case TriplePatternType.Path: IPropertyPathPattern path = (IPropertyPathPattern)tp; output.Append(this.Format(path.Subject, TripleSegment.Subject)); output.Append(' '); output.Append(this.FormatPath(path.Path)); output.Append(' '); output.Append(this.Format(path.Object, TripleSegment.Object)); output.Append(" ."); break; case TriplePatternType.LetAssignment: IAssignmentPattern let = (IAssignmentPattern)tp; output.Append("LET(?"); output.Append(let.VariableName); output.Append(" := "); output.Append(this.FormatExpression(let.AssignExpression)); output.Append(")"); break; case TriplePatternType.BindAssignment: IAssignmentPattern bind = (IAssignmentPattern)tp; output.Append("BIND ("); output.Append(this.FormatExpression(bind.AssignExpression)); output.Append(" AS ?"); output.Append(bind.VariableName); output.Append(")"); break; case TriplePatternType.PropertyFunction: IPropertyFunctionPattern propFunc = (IPropertyFunctionPattern)tp; if (propFunc.SubjectArgs.Count() > 1) { output.Append("( "); foreach (PatternItem arg in propFunc.SubjectArgs) { output.Append(this.Format(arg, TripleSegment.Subject)); output.Append(' '); } output.Append(')'); } else { output.Append(this.Format(propFunc.SubjectArgs.First(), TripleSegment.Subject)); } output.Append(" <"); output.Append(this.FormatUri(propFunc.PropertyFunction.FunctionUri)); output.Append("> "); if (propFunc.ObjectArgs.Count() > 1) { output.Append("( "); foreach (PatternItem arg in propFunc.ObjectArgs) { output.Append(this.Format(arg, TripleSegment.Object)); output.Append(' '); } output.Append(')'); } else { output.Append(this.Format(propFunc.ObjectArgs.First(), TripleSegment.Object)); } output.Append(" ."); break; default: throw new RdfOutputException("Unable to Format an unknown ITriplePattern implementation as a String"); } return(output.ToString()); }
/// <summary> /// Attempts to do variable substitution within the given algebra /// </summary> /// <param name="algebra">Algebra</param> /// <returns></returns> public ISparqlAlgebra Optimise(ISparqlAlgebra algebra) { // By default we are only safe to replace objects in a scope if we are replacing with a constant // Note that if we also make a replace in a subject/predicate position for a variable replace then // that makes object replacement safe for that scope only bool canReplaceObjects = (this._canReplaceCustom ? this._canReplaceObjects : this._replaceItem is NodeMatchPattern); if (algebra is IBgp) { IBgp bgp = (IBgp)algebra; if (bgp.PatternCount == 0) { return(bgp); } // Do variable substitution on the patterns List <ITriplePattern> ps = new List <ITriplePattern>(); foreach (ITriplePattern p in bgp.TriplePatterns) { switch (p.PatternType) { case TriplePatternType.Match: IMatchTriplePattern tp = (IMatchTriplePattern)p; PatternItem subj = tp.Subject.VariableName != null && tp.Subject.VariableName.Equals(this._findVar) ? this._replaceItem : tp.Subject; if (ReferenceEquals(subj, this._replaceItem)) { canReplaceObjects = (this._canReplaceCustom ? this._canReplaceObjects : true); } PatternItem pred = tp.Predicate.VariableName != null && tp.Predicate.VariableName.Equals(this._findVar) ? this._replaceItem : tp.Predicate; if (ReferenceEquals(pred, this._replaceItem)) { canReplaceObjects = (this._canReplaceCustom ? this._canReplaceObjects : true); } PatternItem obj = tp.Object.VariableName != null && tp.Object.VariableName.Equals(this._findVar) ? this._replaceItem : tp.Object; if (ReferenceEquals(obj, this._replaceItem) && !canReplaceObjects) { throw new Exception("Unable to substitute a variable into the object position in this scope"); } ps.Add(new TriplePattern(subj, pred, obj)); break; case TriplePatternType.Filter: IFilterPattern fp = (IFilterPattern)p; ps.Add(new FilterPattern(new UnaryExpressionFilter(this.Transform(fp.Filter.Expression)))); break; case TriplePatternType.BindAssignment: IAssignmentPattern bp = (IAssignmentPattern)p; ps.Add(new BindPattern(bp.VariableName, this.Transform(bp.AssignExpression))); break; case TriplePatternType.LetAssignment: IAssignmentPattern lp = (IAssignmentPattern)p; ps.Add(new LetPattern(lp.VariableName, this.Transform(lp.AssignExpression))); break; case TriplePatternType.SubQuery: throw new RdfQueryException("Cannot do variable substitution when a sub-query is present"); case TriplePatternType.Path: throw new RdfQueryException("Cannot do variable substitution when a property path is present"); case TriplePatternType.PropertyFunction: throw new RdfQueryException("Cannot do variable substituion when a property function is present"); default: throw new RdfQueryException("Cannot do variable substitution on unknown triple patterns"); } } return(new Bgp(ps)); } else if (algebra is Service) { throw new RdfQueryException("Cannot do variable substitution when a SERVICE clause is present"); } else if (algebra is SubQuery) { throw new RdfQueryException("Cannot do variable substitution when a sub-query is present"); } else if (algebra is IPathOperator) { throw new RdfQueryException("Cannot do variable substitution when a property path is present"); } else if (algebra is Algebra.Graph) { Algebra.Graph g = (Algebra.Graph)((IUnaryOperator)algebra).Transform(this); if (g.GraphSpecifier is VariableToken && g.GraphSpecifier.Value.Equals("?" + this._findVar)) { if (this._replaceToken != null) { return(new Algebra.Graph(g.InnerAlgebra, this._replaceToken)); } else { throw new RdfQueryException("Cannot do a variable substitution when the variable is used for a GRAPH specifier and the replacement term is not a URI"); } } else { return(g); } } else if (algebra is IUnaryOperator) { return(((IUnaryOperator)algebra).Transform(this)); } else if (algebra is IAbstractJoin) { return(((IAbstractJoin)algebra).Transform(this)); } else if (algebra is ITerminalOperator) { return(algebra); } else { throw new RdfQueryException("Cannot do variable substitution on unknown algebra"); } }
private void GetSelectivities(ITriplePattern x, out double subj, out double pred, out double obj) { switch (x.PatternType) { case TriplePatternType.Match: IMatchTriplePattern p = (IMatchTriplePattern)x; switch (p.IndexType) { case TripleIndexType.NoVariables: subj = _weights.SubjectWeighting(((NodeMatchPattern)p.Subject).Node); pred = _weights.PredicateWeighting(((NodeMatchPattern)p.Predicate).Node); obj = _weights.ObjectWeighting(((NodeMatchPattern)p.Object).Node); break; case TripleIndexType.Object: subj = _weights.DefaultVariableWeighting; pred = _weights.DefaultVariableWeighting; obj = _weights.ObjectWeighting(((NodeMatchPattern)p.Object).Node); break; case TripleIndexType.Predicate: subj = _weights.DefaultVariableWeighting; pred = _weights.PredicateWeighting(((NodeMatchPattern)p.Predicate).Node); obj = _weights.DefaultVariableWeighting; break; case TripleIndexType.PredicateObject: subj = _weights.DefaultVariableWeighting; pred = _weights.PredicateWeighting(((NodeMatchPattern)p.Predicate).Node); obj = _weights.ObjectWeighting(((NodeMatchPattern)p.Object).Node); break; case TripleIndexType.Subject: subj = _weights.SubjectWeighting(((NodeMatchPattern)p.Subject).Node); pred = _weights.DefaultVariableWeighting; obj = _weights.DefaultVariableWeighting; break; case TripleIndexType.SubjectObject: subj = _weights.SubjectWeighting(((NodeMatchPattern)p.Subject).Node); pred = _weights.DefaultVariableWeighting; obj = _weights.PredicateWeighting(((NodeMatchPattern)p.Object).Node); break; case TripleIndexType.SubjectPredicate: subj = _weights.SubjectWeighting(((NodeMatchPattern)p.Subject).Node); pred = _weights.PredicateWeighting(((NodeMatchPattern)p.Predicate).Node); obj = _weights.DefaultVariableWeighting; break; default: // Shouldn't see an unknown index type but have to keep the compiler happy subj = 1d; pred = 1d; obj = 1d; break; } break; default: // Otherwise all are considered to have equivalent selectivity subj = 1d; pred = 1d; obj = 1d; break; } }
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; //Set up the Input and Output Multiset appropriately switch (pattern) { case 0: //Input is as given and Output is new empty multiset initialInput = context.InputMultiset; localOutput = new Multiset(); break; case 1: //Input becomes current Output and Output is new empty multiset initialInput = context.OutputMultiset; localOutput = new Multiset(); break; default: //Input is join of previous input and ouput and Output is new empty multiset if (context.InputMultiset.IsDisjointWith(context.OutputMultiset)) { //Disjoint so do a Product initialInput = context.InputMultiset.Product(context.OutputMultiset); } else { //Normal Join initialInput = context.InputMultiset.Join(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; if (temp.PatternType == TriplePatternType.Match) { //Find the first Triple which matches the Pattern IMatchTriplePattern tp = (IMatchTriplePattern)temp; foreach (Triple t in tp.GetTriples(context)) { //Remember to check for Timeout during lazy evaluation context.CheckTimeout(); if (tp.Accepts(context, t)) { resultsFound++; 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) { return(results); } //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 context.OutputMultiset = context.InputMultiset.ProductWithTimeout(context.OutputMultiset, context.QueryTimeout - context.QueryTime); } else { //Normal Join context.OutputMultiset = context.InputMultiset.Join(context.OutputMultiset); } return(context.OutputMultiset); } } } } else if (temp.PatternType == TriplePatternType.Filter) { IFilterPattern fp = (IFilterPattern)temp; ISparqlFilter filter = fp.Filter; ISparqlExpression expr = filter.Expression; //Find the first result of those we've got so far that matches if (context.InputMultiset is IdentityMultiset || context.InputMultiset.IsEmpty) { try { //If the Input is the Identity Multiset then the Output is either //the Identity/Null Multiset depending on whether the Expression evaluates to true if (expr.Evaluate(context, 0).AsSafeBoolean()) { context.OutputMultiset = new IdentityMultiset(); } else { context.OutputMultiset = new NullMultiset(); } } catch { //If Expression fails to evaluate then result is NullMultiset context.OutputMultiset = new NullMultiset(); } } else { foreach (int id in context.InputMultiset.SetIDs) { //Remember to check for Timeout during lazy evaluation context.CheckTimeout(); try { if (expr.Evaluate(context, id).AsSafeBoolean()) { resultsFound++; context.OutputMultiset.Add(context.InputMultiset[id].Copy()); //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) { return(results); } //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 context.OutputMultiset = context.InputMultiset.ProductWithTimeout(context.OutputMultiset, context.RemainingTimeout); } else { //Normal Join context.OutputMultiset = context.InputMultiset.Join(context.OutputMultiset); } return(context.OutputMultiset); } } } catch { //Ignore expression evaluation errors } } } } //If we found no possibles we return the null multiset if (resultsFound == 0) { return(new NullMultiset()); } //We should never reach here so throw an error to that effect //The reason we'll never reach here is that this method should always return earlier throw new RdfQueryException("Unexpected control flow in evaluating a Streamed BGP for an ASK query"); }
/// <summary> /// Compares a triple pattern to another. /// </summary> /// <param name="other">Pattern.</param> /// <returns></returns> public int CompareTo(IMatchTriplePattern other) { return(base.CompareTo(other)); }
private BaseMultiset StreamingEvaluate(SparqlEvaluationContext context, int pattern, out bool halt) { // Remember to check for Timeouts during Lazy Evaluation context.CheckTimeout(); halt = false; // Handle Empty BGPs if (pattern == 0 && _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 = (_triplePatterns[pattern].PatternType == TriplePatternType.Filter); bool extended = (pattern > 0 && _triplePatterns[pattern - 1].PatternType == TriplePatternType.BindAssignment); bool modified = (pattern > 0 && _triplePatterns[pattern - 1].PatternType == TriplePatternType.Filter); // 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 = _triplePatterns[pattern]; int resultsFound = 0; int prevResults = -1; if (temp.PatternType == TriplePatternType.Match) { // Find the first Triple which matches the Pattern IMatchTriplePattern tp = (IMatchTriplePattern)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 // Thus required results is everything so just use normal evaluation as otherwise // lazy evaluation will significantly impact performance and lead to an apparent infinite loop return(base.Evaluate(context)); } } } } foreach (Triple t in ts) { 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 < _triplePatterns.Count - 1) { results = StreamingEvaluate(context, pattern + 1, out halt); // If recursion leads to a halt then we halt and return immediately if (halt && results.Count >= _requiredResults && _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 >= _requiredResults && _requiredResults != -1) { context.OutputMultiset = results; return(context.OutputMultiset); } } context.InputMultiset = results; } else if (temp.PatternType == TriplePatternType.Filter) { IFilterPattern filter = (IFilterPattern)temp; ISparqlExpression filterExpr = filter.Filter.Expression; if (filter.Variables.IsDisjoint(context.InputMultiset.Variables)) { // 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 < _triplePatterns.Count - 1) { // Recurse and return results = 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 < _triplePatterns.Count - 1) { // Recurse and return results = 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 { // 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 < _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 = 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 { // 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 < _triplePatterns.Count - 1) { // Recurse then return results = 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 { // Remember to check for Timeouts during Lazy Evaluation context.CheckTimeout(); // 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> /// Optimises the algebra so that all Node terms are virtualised. /// </summary> /// <param name="algebra">Algebra.</param> /// <returns></returns> public ISparqlAlgebra Optimise(ISparqlAlgebra algebra) { if (algebra is IAbstractJoin) { return(((IAbstractJoin)algebra).Transform(this)); } else if (algebra is IUnaryOperator) { return(((IUnaryOperator)algebra).Transform(this)); } else if (algebra is IBgp) { IBgp current = (IBgp)algebra; if (current.PatternCount == 0) { return(current); } else { ISparqlAlgebra result = new Bgp(); List <ITriplePattern> patterns = new List <ITriplePattern>(); List <ITriplePattern> ps = new List <ITriplePattern>(current.TriplePatterns.ToList()); TNodeID nullID = _provider.NullID; for (int i = 0; i < current.PatternCount; i++) { if (ps[i].PatternType == TriplePatternType.Filter || ps[i].PatternType == TriplePatternType.BindAssignment || ps[i].PatternType == TriplePatternType.LetAssignment) { // First ensure that if we've found any other Triple Patterns up to this point // we dump this into a BGP and join with the result so far if (patterns.Count > 0) { result = Join.CreateJoin(result, new Bgp(patterns)); patterns.Clear(); } if (ps[i].PatternType == TriplePatternType.Filter) { result = new Filter(result, new UnaryExpressionFilter(Transform(((IFilterPattern)ps[i]).Filter.Expression))); } else { IAssignmentPattern bind = (IAssignmentPattern)ps[i]; result = new Extend(result, Transform(bind.AssignExpression), bind.VariableName); } } else if (ps[i].PatternType == TriplePatternType.Match) { // Convert Terms in the Pattern into Virtual Nodes IMatchTriplePattern tp = (IMatchTriplePattern)ps[i]; PatternItem subj, pred, obj; if (tp.Subject is NodeMatchPattern) { TNodeID id = _provider.GetID(((NodeMatchPattern)tp.Subject).Node); if (id == null || id.Equals(nullID)) { result = new NullOperator(current.Variables); break; } else { subj = new NodeMatchPattern(CreateVirtualNode(id, ((NodeMatchPattern)tp.Subject).Node)); } } else { subj = tp.Subject; } if (tp.Predicate is NodeMatchPattern) { TNodeID id = _provider.GetID(((NodeMatchPattern)tp.Predicate).Node); if (id == null || id.Equals(nullID)) { result = new NullOperator(current.Variables); break; } else { pred = new NodeMatchPattern(CreateVirtualNode(id, ((NodeMatchPattern)tp.Predicate).Node)); } } else { pred = tp.Predicate; } if (tp.Object is NodeMatchPattern) { TNodeID id = _provider.GetID(((NodeMatchPattern)tp.Object).Node); if (id == null || id.Equals(nullID)) { result = new NullOperator(current.Variables); break; } else { obj = new NodeMatchPattern(CreateVirtualNode(id, ((NodeMatchPattern)tp.Object).Node)); } } else { obj = tp.Object; } patterns.Add(new TriplePattern(subj, pred, obj)); } else { // Can't optimize if other pattern types involved return(current); } } if (result is NullOperator) { return(result); } else if (patterns.Count > 0) { // If any patterns left at end join as a BGP with result so far result = Join.CreateJoin(result, new Bgp(patterns)); return(result); } else { return(result); } } } else if (algebra is ITerminalOperator) { return(algebra); } else { return(algebra); } }
/// <summary> /// Generates a Comparer than can be used to do Ordering based on the given Triple Pattern /// </summary> /// <param name="pattern">Triple Pattern</param> /// <returns></returns> public abstract IComparer <Triple> GetComparer(IMatchTriplePattern pattern);