// Special treatment of nested rdf:Lists private int printTriplePattern(List <IElement> elements, int i, ISparqlPrinter p) { ITriplePattern main = (ITriplePattern)elements[i]; // Print subject List <IResource> leftList = new List <IResource>(); i = addListMembers(elements, i, leftList); if (leftList.Count == 0) { TupleImpl.print(getModel(), main.getSubject(), p); } else { printRDFList(p, leftList); main = (ITriplePattern)elements[i]; } p.print(" "); // Print predicate if (RDFUtil.sameTerm(RDF.PropertyType, main.getPredicate())) { p.print("a"); } else { TupleImpl.print(getModel(), main.getPredicate(), p); } p.print(" "); // Print object if (nextIsMatchingVarPattern(main, elements, i)) { List <IResource> rightList = new List <IResource>(); i = addListMembers(elements, i + 1, rightList); if (rightList.Count == 0) { TupleImpl.print(getModel(), main.getObject(), p); if (leftList.Count != 0) { i--; } } else { printRDFList(p, rightList); i--; } } else { TupleImpl.print(getModel(), main.getObject(), p); } return(i); }
protected CollapseGroup(ITriplePattern tp, IEnumerable <string> sortVariables) { Variables = new List <string>(tp.Variables); SortVariables = new List <string>(); foreach (var sv in sortVariables) { if (tp.Variables.Contains(sv)) { SortVariables.Add(sv); } } }
protected CollapseGroup(ITriplePattern tp, IEnumerable<string> sortVariables) { Variables = new List<string>(tp.Variables); SortVariables = new List<string>(); foreach (var sv in sortVariables) { if (tp.Variables.Contains(sv)) { SortVariables.Add(sv); } } }
public ThreeVarCollapseGroup(IStore store, ITriplePattern tp, IEnumerable<string> globalSortVars, IEnumerable<string> activeGraphUris) : base(tp, globalSortVars) { _store = store; _matchLength = 3; SortVariables = new List<string>(); var triplePattern = tp as TriplePattern; // This is the order we get from the store - pred, subj, obj SortVariables.Add(triplePattern.Predicate.VariableName); SortVariables.Add(triplePattern.Subject.VariableName); SortVariables.Add(triplePattern.Object.VariableName); _graphUris = activeGraphUris; }
public ThreeVarCollapseGroup(IStore store, ITriplePattern tp, IEnumerable <string> globalSortVars, IEnumerable <string> activeGraphUris) : base(tp, globalSortVars) { _store = store; _matchLength = 3; SortVariables = new List <string>(); var triplePattern = tp as TriplePattern; // This is the order we get from the store - pred, subj, obj SortVariables.Add(triplePattern.Predicate.VariableName); SortVariables.Add(triplePattern.Subject.VariableName); SortVariables.Add(triplePattern.Object.VariableName); _graphUris = activeGraphUris; }
internal static INode ToSpinRdf(this ITriplePattern pattern, IGraph g, SpinVariableTable varTable) { INode p = g.CreateBlankNode(); INode rdfType = g.CreateUriNode(new Uri(RdfSpecsHelper.RdfType)); if (pattern is TriplePattern) { TriplePattern tp = (TriplePattern)pattern; //g.Assert(p, rdfType, g.CreateUriNode(new Uri(SpinClassTriplePattern))); g.Assert(p, g.CreateUriNode(new Uri(SpinPropertySubject)), tp.Subject.ToSpinRdf(g, varTable)); g.Assert(p, g.CreateUriNode(new Uri(SpinPropertyPredicate)), tp.Predicate.ToSpinRdf(g, varTable)); g.Assert(p, g.CreateUriNode(new Uri(SpinPropertyObject)), tp.Object.ToSpinRdf(g, varTable)); } else if (pattern is SubQueryPattern) { g.Assert(p, rdfType, g.CreateUriNode(new Uri(SpinClassSubQuery))); g.Assert(p, g.CreateUriNode(new Uri(SpinPropertyQuery)), ((SubQueryPattern)pattern).SubQuery.ToSpinRdf(g)); } else if (pattern is FilterPattern) { g.Assert(p, rdfType, g.CreateUriNode(new Uri(SpinClassFilter))); g.Assert(p, g.CreateUriNode(new Uri(SpinPropertyExpression)), ((FilterPattern)pattern).Filter.Expression.ToSpinRdf(g, varTable)); } else if (pattern is PropertyPathPattern) { PropertyPathPattern pp = (PropertyPathPattern)pattern; g.Assert(p, rdfType, g.CreateUriNode(new Uri(SpinClassTriplePath))); g.Assert(p, g.CreateUriNode(new Uri(SpinPropertySubject)), pp.Subject.ToSpinRdf(g, varTable)); g.Assert(p, g.CreateUriNode(new Uri(SpinPropertyPath)), pp.Path.ToSpinRdf(g, varTable)); g.Assert(p, g.CreateUriNode(new Uri(SpinPropertyObject)), pp.Object.ToSpinRdf(g, varTable)); } else if (pattern is LetPattern) { g.Assert(p, rdfType, g.CreateUriNode(new Uri(SpinClassLet))); INode var = g.CreateBlankNode(); g.Assert(p, g.CreateUriNode(new Uri(SpinPropertyVariable)), var); g.Assert(var, g.CreateUriNode(new Uri(SpinPropertyVariableName)), g.CreateLiteralNode(((LetPattern)pattern).VariableName, new Uri(XmlSpecsHelper.XmlSchemaDataTypeString))); g.Assert(p, g.CreateUriNode(new Uri(SpinPropertyExpression)), ((LetPattern)pattern).AssignExpression.ToSpinRdf(g, varTable)); } else if (pattern is BindPattern) { throw new SpinException("SPARQL 1.1 BINDs are not representable in SPIN RDF Syntax"); } return(p); }
/// <summary> /// Compares a Triple Pattern to another Triple Pattern /// </summary> /// <param name="other">Other Triple Pattern</param> /// <returns></returns> /// <remarks> /// <para> /// The aim of this function is to sort Triple Patterns into what is hopefully an optimal order such that during execution the query space is restricted as early as possible. /// </para> /// <para> /// The basic rules of this are as follows: /// <ol> /// <li>Patterns with fewer variables should be executed first</li> /// <li>Patterns using the same variables should be executed in sequence</li> /// <li>Patterns using indexes which are considered more useful should be executed first</li> /// </ol> /// </para> /// </remarks> public virtual int CompareTo(ITriplePattern other) { if (this._vars.Count < other.Variables.Count) { //We have fewer variables so we go before the other pattern return(-1); } else if (this._vars.Count > other.Variables.Count) { //We have more variables so we go after the other pattern return(1); } else { if (this._vars.Count > 0) { for (int i = 0; i < this._vars.Count; i++) { int c = this._vars[i].CompareTo(other.Variables[i]); if (c < 0) { //Our variables occur alphabetically sooner than the other patterns so we go before the other pattern return(-1); } else if (c > 0) { //Other variables occur alphabetically sooner than ours so we go after return(1); } //Otherwise we continue checking } //If we reach this point then we contain the same variables //Now we order based on our Index Types TripleIndexSorter sorter = new TripleIndexSorter(); return(sorter.Compare(this.IndexType, other.IndexType)); } else { //Neither pattern has any variables so we consider these to be equivalent //Order of these patterns has no effect return(0); } } }
internal static INode ToSpinRdf(this ITriplePattern pattern, IGraph g, SpinVariableTable varTable) { INode p = g.CreateBlankNode(); if (pattern is TriplePattern) { TriplePattern tp = (TriplePattern)pattern; g.Assert(p, RDF.PropertyType, SP.ClassTriplePattern); g.Assert(p, SP.PropertySubject, tp.Subject.ToSpinRdf(g, varTable)); g.Assert(p, SP.PropertyPredicate, tp.Predicate.ToSpinRdf(g, varTable)); g.Assert(p, SP.PropertyObject, tp.Object.ToSpinRdf(g, varTable)); } else if (pattern is SubQueryPattern) { g.Assert(p, RDF.PropertyType, SP.ClassSubQuery); g.Assert(p, SP.PropertyQuery, ((SubQueryPattern)pattern).SubQuery.ToSpinRdf(g)); } else if (pattern is FilterPattern) { g.Assert(p, RDF.PropertyType, SP.ClassFilter); g.Assert(p, SP.PropertyExpression, ((FilterPattern)pattern).Filter.Expression.ToSpinRdf(g, varTable)); } else if (pattern is PropertyPathPattern) { PropertyPathPattern pp = (PropertyPathPattern)pattern; g.Assert(p, RDF.PropertyType, SP.ClassTriplePath); g.Assert(p, SP.PropertySubject, pp.Subject.ToSpinRdf(g, varTable)); g.Assert(p, SP.PropertyPath, pp.Path.ToSpinRdf(g, varTable)); g.Assert(p, SP.PropertyObject, pp.Object.ToSpinRdf(g, varTable)); } else if (pattern is LetPattern) { g.Assert(p, RDF.PropertyType, SP.ClassLet); INode var = g.CreateBlankNode(); g.Assert(p, SP.PropertyVariable, var); g.Assert(var, SP.PropertyVarName, g.CreateLiteralNode(((LetPattern)pattern).VariableName, XSD.string_.Uri)); g.Assert(p, SP.PropertyExpression, ((LetPattern)pattern).AssignExpression.ToSpinRdf(g, varTable)); } else if (pattern is BindPattern) { throw new SpinException("SPARQL 1.1 BINDs are not representable in SPIN RDF Syntax"); } return(p); }
/// <summary> /// Adds a Triple Pattern to the Graph Pattern respecting any BGP breaks /// </summary> /// <param name="p">Triple Pattern</param> internal void AddTriplePattern(ITriplePattern p) { if (_break) { if (_broken) { _graphPatterns.Last().AddTriplePattern(p); } else { GraphPattern breakPattern = new GraphPattern(); breakPattern.AddTriplePattern(p); _graphPatterns.Add(breakPattern); } } else { _triplePatterns.Add(p); } }
private int addListMembers(List <IElement> elements, int i, List <IResource> members) { bool first = true; while (i < elements.Count - 1 && elements[i] is ITriplePattern && elements[i + 1] is ITriplePattern) { ITriplePattern firstPattern = (ITriplePattern)elements[i]; ITriplePattern secondPattern = (ITriplePattern)elements[i + 1]; if (RDFUtil.sameTerm(RDF.PropertyFirst, firstPattern.getPredicate()) && RDFUtil.sameTerm(RDF.PropertyRest, secondPattern.getPredicate())) { IResource firstSubject = firstPattern.getSubject(); IResource secondSubject = secondPattern.getSubject(); if (firstSubject is IVariable && secondSubject is IVariable) { IVariable firstVar = (IVariable)firstSubject; IVariable secondVar = (IVariable)secondSubject; if (firstVar.isBlankNodeVar() && firstVar.getName().Equals(secondVar.getName())) { members.Add(firstPattern.getObject()); IResource secondObject = secondPattern.getObject(); i++; if (RDFUtil.sameTerm(RDF.Nil, secondObject)) { return(i + 1); } } } } // We are not in a valid list if (first && members.Count == 0) { break; } first = false; i++; } return(i); }
private static void AddTriplePattern(GraphPattern graphPattern, ITriplePattern tp) { switch (tp.PatternType) { case TriplePatternType.Match: case TriplePatternType.Path: case TriplePatternType.PropertyFunction: case TriplePatternType.SubQuery: graphPattern.AddTriplePattern(tp); break; case TriplePatternType.LetAssignment: case TriplePatternType.BindAssignment: graphPattern.AddAssignment((IAssignmentPattern)tp); break; case TriplePatternType.Filter: graphPattern.AddFilter(((IFilterPattern)tp).Filter); break; } }
/// <summary> /// Creates a Streamed BGP containing a single Triple Pattern /// </summary> /// <param name="p">Triple Pattern</param> /// <param name="requiredResults">The number of Results the BGP should attempt to return</param> public LazyBgp(ITriplePattern p, int requiredResults) { if (!IsLazilyEvaluablePattern(p)) throw new ArgumentException("Triple Pattern instance must be a Triple Pattern, BIND or FILTER Pattern", "p"); this._requiredResults = requiredResults; this._triplePatterns.Add(p); }
/// <summary> /// Adds a Triple Pattern to the Path Transform /// </summary> /// <param name="p">Triple Pattern</param> public void AddTriplePattern(ITriplePattern p) { this._patterns.Add(p); }
/// <summary> /// Creates a Streamed BGP containing a single Triple Pattern /// </summary> /// <param name="p">Triple Pattern</param> public LazyBgp(ITriplePattern p) { if (!IsLazilyEvaluablePattern(p)) throw new ArgumentException("Triple Pattern instance must be a Triple Pattern or a Subquery, BIND or FILTER Pattern", "p"); this._triplePatterns.Add(p); }
private bool IsDisjointOperation(ISparqlAlgebra algebra, List <String> filterVars, out int splitPoint) { splitPoint = -1; if (algebra is IBgp) { // Get Triple Patterns, can't split into a product if there are blank variables present List <ITriplePattern> ps = ((IBgp)algebra).TriplePatterns.ToList(); if (ps.Any(p => !p.HasNoBlankVariables)) { return(false); } // Iterate over the Triple Patterns to see if we can split into a Product List <String> vars = new List <String>(); for (int i = 0; i < ps.Count; i++) { // Not a product if we've seen both variables already if (filterVars.All(v => vars.Contains(v))) { return(false); } ITriplePattern p = ps[i]; if (p.PatternType == TriplePatternType.Match || p.PatternType == TriplePatternType.SubQuery) { if (vars.Count > 0 && vars.IsDisjoint(p.Variables)) { // Is a filterable product if we've not seen all the variables so far and have hit a point where a product occurs // and all the variables are not in the RHS Bgp rhs = new Bgp(ps.Skip(i)); if (!filterVars.All(v => rhs.Variables.Contains(v))) { splitPoint = i; return(true); } } vars.AddRange(p.Variables); } else if (p.PatternType == TriplePatternType.BindAssignment || p.PatternType == TriplePatternType.LetAssignment) { vars.Add(((IAssignmentPattern)p).VariableName); } else if (p.PatternType == TriplePatternType.Filter) { continue; } else { return(false); } } // If we get all the way here then not a product return(false); } else if (algebra is IJoin) { IJoin join = (IJoin)algebra; if (join.Lhs.Variables.IsDisjoint(join.Rhs.Variables)) { // There a product between the two sides of the join but are the variables spead over different sides of that join? // If all variables occur on one side then this is not a filtered product return(!filterVars.All(v => join.Lhs.Variables.Contains(v)) && !filterVars.All(v => join.Rhs.Variables.Contains(v))); } else { return(false); } } else { return(false); } }
private bool IsLazilyEvaluablePattern(ITriplePattern p) { return(p.PatternType == TriplePatternType.Match || p.PatternType == TriplePatternType.Filter || p.PatternType == TriplePatternType.BindAssignment); }
/// <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(); if (tp is TriplePattern) { TriplePattern match = (TriplePattern)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(" ."); } else if (tp is FilterPattern) { FilterPattern filter = (FilterPattern)tp; output.Append("FILTER("); output.Append(this.FormatExpression(filter.Filter.Expression)); output.Append(")"); } else if (tp is SubQueryPattern) { SubQueryPattern subquery = (SubQueryPattern)tp; output.AppendLine("{"); output.AppendLineIndented(this.Format(subquery.SubQuery), 2); output.AppendLine("}"); } else if (tp is PropertyPathPattern) { PropertyPathPattern path = (PropertyPathPattern)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(" ."); } else if (tp is LetPattern) { LetPattern let = (LetPattern)tp; output.Append("LET(?"); output.Append(let.VariableName); output.Append(" := "); output.Append(this.FormatExpression(let.AssignExpression)); output.Append(")"); } else if (tp is BindPattern) { BindPattern bind = (BindPattern)tp; output.Append("BIND ("); output.Append(this.FormatExpression(bind.AssignExpression)); output.Append(" AS ?"); output.Append(bind.VariableName); output.Append(")"); } else { throw new RdfOutputException("Unable to Format an unknown ITriplePattern implementation as a String"); } return(output.ToString()); }
/// <summary> /// Creates a BGP containing a single Triple Pattern. /// </summary> /// <param name="p">Triple Pattern.</param> public Bgp(ITriplePattern p) { _triplePatterns.Add(p); }
override protected void handleTriplePattern(ITriplePattern triplePattern, Dictionary <IResource, IResource> bindings) { bool valid = false; IResource subject = triplePattern.getSubject(); if (RDFUtil.sameTerm(SPIN.Property_this, subject)) { valid = true; } else if (bindings != null) { IVariable var = SPINFactory.asVariable(subject); if (var != null) { String varName = var.getName(); foreach (IResource argPredicate in bindings.Keys) { if (varName.Equals(argPredicate.Uri().ToString().Replace(SP.BASE_URI, "").Replace(SPIN.BASE_URI, ""))) { IResource b = bindings[argPredicate]; if (RDFUtil.sameTerm(SPIN.Property_this, b)) { valid = true; break; } } } } } if (valid) { IResource predicate = triplePattern.getPredicate(); if (predicate != null) { IVariable variable = SPINFactory.asVariable(predicate); if (variable == null) { Uri uri = predicate.Uri(); if (uri != null) { properties.Add(Resource.Get(predicate, _targetModel)); } } else if (bindings != null) { String varName = variable.getName(); foreach (IResource argPredicate in bindings.Keys) { if (varName.Equals(argPredicate.Uri().ToString().Replace(SP.BASE_URI, "").Replace(SPIN.BASE_URI, ""))) { IResource b = bindings[argPredicate]; if (b != null && b.isUri()) { properties.Add(Resource.Get(b, _targetModel)); } } } } } } }
public PassthroughCollapseGroup(ITriplePattern tp, IEnumerable <string> globalSortVars) : base(tp, globalSortVars) { _triplePattern = tp; }
/** * Checks whether a given INode represents a SPARQL element, and returns * an instance of a subclass of Element if so. * @param resource the INode to check * @return INode as an Element or null if resource is not an element */ public static IElement asElement(IResource resource) { if (resource == null) { return(null); } /*sealed*/ ITriplePattern triplePattern = asTriplePattern(resource); if (triplePattern != null) { return(triplePattern); } else if (resource.canAs(SP.ClassTriplePath)) { return((ITriplePath)resource.As(typeof(TriplePathImpl))); } else if (resource.canAs(SP.ClassFilter)) { return((IFilter)resource.As(typeof(FilterImpl))); } else if (resource.canAs(SP.ClassBind)) { return((IBind)resource.As(typeof(BindImpl))); } else if (resource.canAs(SP.ClassOptional)) { return((IOptional)resource.As(typeof(OptionalImpl))); } else if (resource.canAs(SP.ClassNamedGraph)) { return((INamedGraph)resource.As(typeof(NamedGraphImpl))); } else if (resource.canAs(SP.ClassMinus)) { return((IMinus)resource.As(typeof(MinusImpl))); } else if (resource.canAs(SP.ClassExists)) { return((IExists)resource.As(typeof(ExistsImpl))); } else if (resource.canAs(SP.ClassNotExists)) { return((INotExists)resource.As(typeof(NotExistsImpl))); } else if (resource.canAs(SP.ClassService)) { return((IService)resource.As(typeof(ServiceImpl))); } else if (resource.canAs(SP.ClassSubQuery)) { return((ISubQuery)resource.As(typeof(SubQueryImpl))); } else if (resource.canAs(SP.ClassUnion)) { return((IUnion)resource.As(typeof(UnionImpl))); } else if (resource.canAs(SP.ClassValues)) { return((IValues)resource.As(typeof(ValuesImpl))); } else if (isElementList(resource)) { return((IElementList)resource.As(typeof(ElementListImpl))); } else { return(null); } }
/// <summary> /// Adds a Triple Pattern to the Graph Pattern respecting any BGP breaks /// </summary> /// <param name="p">Triple Pattern</param> internal void AddTriplePattern(ITriplePattern p) { if (this._break) { if (this._broken) { this._graphPatterns.Last().AddTriplePattern(p); } else { GraphPattern breakPattern = new GraphPattern(); breakPattern.AddTriplePattern(p); this._graphPatterns.Add(breakPattern); } } else { this._triplePatterns.Add(p); } }
private bool IsLazilyEvaluablePattern(ITriplePattern p) { return (p is TriplePattern || p is FilterPattern || p is BindPattern); }
/// <summary> /// Optimises the algebra to include property functions /// </summary> /// <param name="algebra">Algebra</param> /// <returns></returns> public ISparqlAlgebra Optimise(ISparqlAlgebra algebra) { if (algebra is IBgp) { IBgp current = (IBgp)algebra; if (current.PatternCount == 0) { return(current); } List <ITriplePattern> ps = current.TriplePatterns.ToList(); List <IPropertyFunctionPattern> propFuncs = PropertyFunctionHelper.ExtractPatterns(ps, _factories.Value); if (propFuncs.Count == 0) { return(current); } // Remove raw Triple Patterns pertaining to extracted property functions foreach (IPropertyFunctionPattern propFunc in propFuncs) { // Track where we need to insert the property function back into the BGP ITriplePattern first = propFunc.OriginalPatterns.First(); int origLocation = ps.FindIndex(p => p.Equals(first)); foreach (ITriplePattern tp in propFunc.OriginalPatterns) { int location = ps.FindIndex(p => p.Equals(tp)); if (location >= 0) { if (location < origLocation) { origLocation--; } ps.RemoveAt(location); } else { throw new RdfQueryException("Bad Property Function extraction"); } } // Make the insert if (origLocation >= ps.Count || origLocation < 0 || ps.Count == 0) { ps.Add(propFunc); } else { ps.Insert(origLocation, propFunc); } } // Return a new BGP return(new Bgp(ps)); } else if (algebra is ITerminalOperator) { return(algebra); } else if (algebra is IAbstractJoin) { return(((IAbstractJoin)algebra).Transform(this)); } else if (algebra is IUnaryOperator) { return(((IUnaryOperator)algebra).Transform(this)); } else { return(algebra); } }
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> /// Compares a Triple Pattern to another Triple Pattern /// </summary> /// <param name="other">Other Triple Pattern</param> /// <returns></returns> /// <remarks> /// <para> /// The aim of this function is to sort Triple Patterns into what is hopefully an optimal order such that during execution the query space is restricted as early as possible. /// </para> /// <para> /// The basic rules of this are as follows: /// <ol> /// <li>Patterns with fewer variables should be executed first</li> /// <li>Patterns using the same variables should be executed in sequence</li> /// <li>Patterns using indexes which are considered more useful should be executed first</li> /// </ol> /// </para> /// </remarks> public virtual int CompareTo(ITriplePattern other) { if (this._vars.Count < other.Variables.Count) { //We have fewer variables so we go before the other pattern return -1; } else if (this._vars.Count > other.Variables.Count) { //We have more variables so we go after the other pattern return 1; } else { if (this._vars.Count > 0) { for (int i = 0; i < this._vars.Count; i++) { int c = this._vars[i].CompareTo(other.Variables[i]); if (c < 0) { //Our variables occur alphabetically sooner than the other patterns so we go before the other pattern return -1; } else if (c > 0) { //Other variables occur alphabetically sooner than ours so we go after return 1; } //Otherwise we continue checking } //If we reach this point then we contain the same variables //Now we order based on our Index Types TripleIndexSorter sorter = new TripleIndexSorter(); return sorter.Compare(this.IndexType, other.IndexType); } else { //Neither pattern has any variables so we consider these to be equivalent //Order of these patterns has no effect return 0; } } }
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> /// Creates a Streamed BGP containing a single Triple Pattern /// </summary> /// <param name="p">Triple Pattern</param> public AskBgp(ITriplePattern p) { if (!IsAskEvaluablePattern(p)) throw new ArgumentException("Triple Pattern instance must be a Triple Pattern or a FILTER Pattern", "p"); this._triplePatterns.Add(p); }
/// <summary> /// Determines whether a Triple Pattern can be evaluated using a Lazy ASK approach /// </summary> /// <param name="p">Triple Pattern</param> /// <returns></returns> private bool IsAskEvaluablePattern(ITriplePattern p) { return(p is TriplePattern || p is FilterPattern); }
private bool IsLazilyEvaluablePattern(ITriplePattern p) { return(p is TriplePattern || p is FilterPattern || p is BindPattern); }
/// <summary> /// Determines whether a Triple Pattern can be evaluated using a Lazy ASK approach /// </summary> /// <param name="p">Triple Pattern</param> /// <returns></returns> private bool IsAskEvaluablePattern(ITriplePattern p) { return (p is TriplePattern || p is FilterPattern); }
private bool IsDisjointOperation(ISparqlAlgebra algebra, String lhsVar, String rhsVar, out int splitPoint) { splitPoint = -1; if (algebra is IBgp) { // Get Triple Patterns, can't split into a product if there are blank variables present List <ITriplePattern> ps = ((IBgp)algebra).TriplePatterns.ToList(); if (ps.Any(p => !p.HasNoBlankVariables)) { return(false); } // Iterate over the Triple Patterns to see if we can split into a Product List <String> vars = new List <String>(); for (int i = 0; i < ps.Count; i++) { // Not a product if we've seen both variables already if (vars.Contains(lhsVar) && vars.Contains(rhsVar)) { return(false); } ITriplePattern p = ps[i]; switch (p.PatternType) { case TriplePatternType.Match: case TriplePatternType.SubQuery: if (vars.Count > 0 && vars.IsDisjoint(p.Variables)) { // May be a filterable product if we've seen only one variable so far and have hit a point where a product occurs if (vars.Contains(lhsVar) && !vars.Contains(rhsVar)) { Bgp rhs = new Bgp(ps.Skip(i)); if (rhs.Variables.Contains(rhsVar)) { splitPoint = i; return(true); } } else if (vars.Contains(rhsVar) && !vars.Contains(lhsVar)) { Bgp rhs = new Bgp(ps.Skip(i)); if (rhs.Variables.Contains(lhsVar)) { splitPoint = i; return(true); } } } vars.AddRange(p.Variables); break; case TriplePatternType.BindAssignment: case TriplePatternType.LetAssignment: vars.Add(((IAssignmentPattern)p).VariableName); break; case TriplePatternType.Filter: continue; default: // Can't determine if it is a disjoint operation if other pattern types are involved return(false); } } // If we get all the way here then not a product return(false); } else if (algebra is IJoin) { IJoin join = (IJoin)algebra; if (join.Lhs.Variables.IsDisjoint(join.Rhs.Variables)) { // There a product between the two sides of the join but are the two variables on different sides of that join return(!(join.Lhs.Variables.Contains(lhsVar) && join.Lhs.Variables.Contains(rhsVar)) && !(join.Rhs.Variables.Contains(lhsVar) && join.Rhs.Variables.Contains(rhsVar))); } else { return(false); } } else { return(false); } }
/// <summary> /// Optimises the Algebra so that BGPs containing relevant patterns are converted to use the <see cref="FullTextMatch">FullTextMatch</see> operator /// </summary> /// <param name="algebra">Algebra to optimise</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 <FullTextPattern> fps = FullTextHelper.ExtractPatterns(current.TriplePatterns); if (fps.Count == 0) { return(algebra); } List <ITriplePattern> ps = current.TriplePatterns.ToList(); //First we want to find where each FullTextPattern is located in the original triple patterns Dictionary <int, int> locations = new Dictionary <int, int>(); for (int i = 0; i < fps.Count; i++) { locations.Add(i, -1); ITriplePattern first = fps[i].OriginalPatterns.First(); for (int j = 0; j < ps.Count; j++) { if (first.Equals(ps[j])) { locations[i] = j; break; } } //If we fail to locate this we've failed to optimise here so must abort if (locations[i] == -1) { return(algebra); } } //Knowing this we can then start splitting the BGP into several BGPs int locBase = 0; foreach (int i in Enumerable.Range(0, fps.Count).OrderBy(x => locations[x]).ToList()) { //Wrap everything up to that point in a BGP excluding any patterns relevant to any FullTextPattern result = Join.CreateJoin(result, new Bgp(ps.Skip(locBase).Take(locations[i]).Where(tp => !(tp is TriplePattern) || !fps.Any(fp => fp.OriginalPatterns.Contains((TriplePattern)tp))))); locBase = locations[i] + 1; //Then apply the FullTextMatch operator over it FullTextPattern ftp = fps[i]; result = new FullTextMatch(this._provider, result, ftp.MatchVariable, ftp.ScoreVariable, ftp.SearchTerm, ftp.Limit, ftp.ScoreThreshold); } //If there are any patterns left over remember to include them if (locBase < ps.Count) { result = Join.CreateJoin(result, new Bgp(ps.Skip(locBase).Where(tp => !(tp is TriplePattern) || !fps.Any(fp => fp.OriginalPatterns.Contains((TriplePattern)tp))))); } return(result); //List<ITriplePattern> patterns = new List<ITriplePattern>(); //List<ITriplePattern> ps = new List<ITriplePattern>(current.TriplePatterns.ToList()); //for (int i = 0; i < current.PatternCount; i++) //{ // if (!(ps[i] is TriplePattern)) // { // patterns.Add(ps[i]); // } // else // { // //Check to see if the Predicate of the Pattern match the Full Text Match Predicate URI // TriplePattern tp = (TriplePattern)ps[i]; // PatternItem pred = tp.Predicate; // if (pred is NodeMatchPattern) // { // INode predNode = ((NodeMatchPattern)pred).Node; // if (predNode.NodeType == NodeType.Uri) // { // String predUri = ((IUriNode)predNode).Uri.ToString(); // if (predUri.Equals(FullTextHelper.FullTextMatchPredicateUri)) // { // if (patterns.Count > 0) result = Join.CreateJoin(result, new Bgp(patterns)); // result = new FullTextMatch(this._provider, result, tp.Subject, tp.Object); // patterns.Clear(); // } // else // { // patterns.Add(ps[i]); // } // } // else // { // patterns.Add(ps[i]); // } // } // else // { // patterns.Add(ps[i]); // } // } //} //if (patterns.Count == current.PatternCount) //{ // //If count of remaining patterns same as original pattern count there was no optimisation // //to do so return as is // return current; //} //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> /// Determines whether a Triple Pattern can be evaluated using a Lazy ASK approach /// </summary> /// <param name="p">Triple Pattern</param> /// <returns></returns> private bool IsAskEvaluablePattern(ITriplePattern p) { return(p.PatternType == TriplePatternType.Match || p.PatternType == TriplePatternType.Filter); }
/// <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(); if (tp is TriplePattern) { TriplePattern match = (TriplePattern)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(" ."); } else if (tp is FilterPattern) { FilterPattern filter = (FilterPattern)tp; output.Append("FILTER("); output.Append(this.FormatExpression(filter.Filter.Expression)); output.Append(")"); } else if (tp is SubQueryPattern) { SubQueryPattern subquery = (SubQueryPattern)tp; output.AppendLine("{"); output.AppendLineIndented(this.Format(subquery.SubQuery), 2); output.AppendLine("}"); } else if (tp is PropertyPathPattern) { PropertyPathPattern path = (PropertyPathPattern)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(" ."); } else if (tp is LetPattern) { LetPattern let = (LetPattern)tp; output.Append("LET(?"); output.Append(let.VariableName); output.Append(" := "); output.Append(this.FormatExpression(let.AssignExpression)); output.Append(")"); } else if (tp is BindPattern) { BindPattern bind = (BindPattern)tp; output.Append("BIND ("); output.Append(this.FormatExpression(bind.AssignExpression)); output.Append(" AS ?"); output.Append(bind.VariableName); output.Append(")"); } else { throw new RdfOutputException("Unable to Format an unknown ITriplePattern implementation as a String"); } return output.ToString(); }
private void ProcessSkipTopFilterOrderBy() { if (QueryOptions.Skip != null || QueryOptions.Top != null || (QueryOptions.OrderBy != null && QueryOptions.OrderBy.OrderByClause != null)) { NodeFactory nodeFactory = new NodeFactory(); var edmNode = EdmNodeList[EdmNodeList.Count - 1]; ITriplePattern[] tps; List <ITriplePattern> optionList = new List <ITriplePattern>(); if (EdmNodeList.Count > 1 && (EdmNodeList[EdmNodeList.Count - 2].RdfNode is NodeMatchPattern)) { var prevEdmNode = EdmNodeList[EdmNodeList.Count - 2]; Dictionary <string, Tuple <Type, Uri> > properties = GetAllProperties(prevEdmNode.ItemEdmType); tps = new ITriplePattern[] { new TriplePattern(prevEdmNode.RdfNode, new NodeMatchPattern(nodeFactory.CreateUriNode(new Uri(properties[edmNode.RdfNode.VariableName].Item2.AbsoluteUri))), edmNode.RdfNode), new TriplePattern(edmNode.RdfNode, new NodeMatchPattern(nodeFactory.CreateUriNode(new Uri(RdfSpecsHelper.RdfType))), new NodeMatchPattern(nodeFactory.CreateUriNode(GetUri(edmNode.ItemEdmType)))) }; foreach (var prop in edmNode.StructProperties.Where(p => p.Name != "LocalId")) { var propTriple = new TriplePattern(edmNode.RdfNode, new NodeMatchPattern(nodeFactory.CreateUriNode(new Uri(properties[prop.Name].Item2.AbsoluteUri))), new VariablePattern($"{prop.Name}")); optionList.Add(propTriple); } } else { tps = new ITriplePattern[] { new TriplePattern(edmNode.RdfNode, new NodeMatchPattern(nodeFactory.CreateUriNode(new Uri(RdfSpecsHelper.RdfType))), new NodeMatchPattern(nodeFactory.CreateUriNode(GetUri(edmNode.ItemEdmType)))) }; Dictionary <string, Tuple <Type, Uri> > properties = GetAllProperties(edmNode.ItemEdmType); foreach (var prop in edmNode.StructProperties.Where(p => p.Name != "LocalId")) { var propTriple = new TriplePattern(edmNode.RdfNode, new NodeMatchPattern(nodeFactory.CreateUriNode(new Uri(properties[prop.Name].Item2.AbsoluteUri))), new VariablePattern($"{prop.Name}")); optionList.Add(propTriple); } } IQueryBuilder subqueryBuilder = QueryBuilder.Select(new string[] { edmNode.Name }). Where(tps); foreach (var tp in optionList) { subqueryBuilder.Optional(gp => gp.Where(tp)); } if (QueryOptions.Skip != null) { subqueryBuilder = subqueryBuilder.Offset(QueryOptions.Skip.Value); } if (QueryOptions.Top != null) { subqueryBuilder = subqueryBuilder.Limit(QueryOptions.Top.Value); } if (FilterExp != null) { subqueryBuilder = subqueryBuilder.Filter(FilterExp); FilterExp = null; } if (QueryOptions.OrderBy != null && QueryOptions.OrderBy.OrderByClause != null) { foreach (var node in QueryOptions.OrderBy.OrderByNodes) { var typedNode = node as OrderByPropertyNode; var ordName = typedNode.Property.Name; if (ordName.ToLower() == "localid") { ordName = edmNode.Name; } if (typedNode.OrderByClause.Direction == OrderByDirection.Ascending) { subqueryBuilder.OrderBy(ordName); } else { subqueryBuilder.OrderByDescending(ordName); } } } SubQueryTriplePatterns.Add(new SubQueryPattern(subqueryBuilder.BuildQuery())); } }
/// <summary> /// Creates a BGP containing a single Triple Pattern /// </summary> /// <param name="p">Triple Pattern</param> public Bgp(ITriplePattern p) { this._triplePatterns.Add(p); }
/// <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()); }
public PassthroughCollapseGroup(ITriplePattern tp, IEnumerable<string> globalSortVars):base(tp, globalSortVars) { _triplePattern = tp; }