/// <summary> /// Converts the Minus() back to a MINUS Graph Pattern /// </summary> /// <returns></returns> public GraphPattern ToGraphPattern() { GraphPattern p = _lhs.ToGraphPattern(); GraphPattern opt = _rhs.ToGraphPattern(); if (!opt.HasModifier) { opt.IsMinus = true; p.AddGraphPattern(opt); } else { GraphPattern parent = new GraphPattern(); parent.AddGraphPattern(opt); parent.IsMinus = true; p.AddGraphPattern(parent); } return(p); }
/// <summary> /// Converts the Algebra into a Graph Pattern. /// </summary> /// <returns></returns> public GraphPattern ToGraphPattern() { GraphPattern p = new GraphPattern(_pattern); if (!p.HasModifier) { p.IsService = true; p.GraphSpecifier = _endpointSpecifier; return(p); } else { GraphPattern parent = new GraphPattern(); parent.IsService = true; parent.GraphSpecifier = _endpointSpecifier; parent.AddGraphPattern(p); return(parent); } }
private GraphPattern TryParseModifyTemplate(SparqlUpdateParserContext context) { SparqlQueryParserContext subContext = new SparqlQueryParserContext(context.Tokens); subContext.Query.BaseUri = context.BaseUri; subContext.Query.NamespaceMap = context.NamespaceMap; subContext.ExpressionParser.NamespaceMap = context.NamespaceMap; subContext.ExpressionParser.ExpressionFactories = context.ExpressionFactories; subContext.ExpressionFactories = context.ExpressionFactories; subContext.ExpressionParser.QueryParser = context.QueryParser; GraphPattern gp = context.QueryParser.TryParseGraphPattern(subContext, context.Tokens.LastTokenType != Token.LEFTCURLYBRACKET); // Validate that the Graph Pattern is simple // Check it doesn't contain anything other than Triple Patterns or if it does it just contains a single GRAPH Pattern if (gp.IsFiltered) { throw new RdfParseException("A FILTER Clause cannot occur in a Modify Template"); } else if (gp.IsOptional) { throw new RdfParseException("An OPTIONAL Clause cannot occur in a Modify Template"); } else if (gp.IsUnion) { throw new RdfParseException("A UNION Clause cannot occur in a Modify Template"); } else if (gp.HasChildGraphPatterns) { if (gp.ChildGraphPatterns.All(p => p.IsGraph && !p.IsFiltered && !p.IsOptional && !p.IsUnion && !p.HasChildGraphPatterns)) { return(gp); } else { throw new RdfParseException("Nested Graph Patterns cannot occur in a Modify Template"); } } else { return(gp); } }
/// <summary> /// Determines whether a Graph Pattern is valid for use in an DELETE pattern. /// </summary> /// <param name="p">Graph Pattern.</param> /// <param name="top">Is this the top level pattern?.</param> /// <returns></returns> protected bool IsValidDeletePattern(GraphPattern p, bool top) { if (p.IsGraph) { // If a GRAPH clause then all triple patterns must be constructable and have no Child Graph Patterns return(!p.HasChildGraphPatterns && p.TriplePatterns.All(tp => tp is IConstructTriplePattern && ((IConstructTriplePattern)tp).HasNoBlankVariables)); } else if (p.IsExists || p.IsMinus || p.IsNotExists || p.IsOptional || p.IsService || p.IsSubQuery || p.IsUnion) { // EXISTS/MINUS/NOT EXISTS/OPTIONAL/SERVICE/Sub queries/UNIONs are not permitted return(false); } else { // For other patterns all Triple patterns must be constructable with no blank variables // If top level then any Child Graph Patterns must be valid // Otherwise must have no Child Graph Patterns return(p.TriplePatterns.All(tp => tp is IConstructTriplePattern && ((IConstructTriplePattern)tp).HasNoBlankVariables) && ((top && p.ChildGraphPatterns.All(gp => IsValidDeletePattern(gp, false))) || !p.HasChildGraphPatterns)); } }
/// <summary> /// Converts the Algebra back to a SPARQL Query /// </summary> /// <returns></returns> public GraphPattern ToGraphPattern() { GraphPattern p = this._lhs.ToGraphPattern(); GraphPattern opt = this._rhs.ToGraphPattern(); opt.IsOptional = true; if (this._filter.Expression is BooleanExpressionTerm) { if (!this._filter.Expression.EffectiveBooleanValue(null, 0)) { opt.Filter = this._filter; } } else { opt.Filter = this._filter; } p.AddGraphPattern(opt); return(p); }
private static void BindPath(GraphPattern pattern, ISparqlPath path) { for (var i = 0; i < pattern.TriplePatterns.Count(); i++) { if (pattern.TriplePatterns[i] is TriplePattern triplePattern && triplePattern.Predicate.VariableName == "PATH") { pattern.TriplePatterns.RemoveAt(i); pattern.TriplePatterns.Insert(i, new PropertyPathPattern(triplePattern.Subject, path, triplePattern.Object)); } } foreach (var subPattern in pattern.ChildGraphPatterns) { BindPath(subPattern, path); } foreach (var subQueryPattern in pattern.TriplePatterns.OfType <SubQueryPattern>()) { BindPath(subQueryPattern.SubQuery.RootGraphPattern, path); } }
public void SparqlGraphPatternToAlgebra5() { GraphPattern gp = new GraphPattern(); gp.IsGraph = true; gp.GraphSpecifier = new VariableToken("g", 0, 0, 1); gp.AddInlineData(new BindingsPattern()); ISparqlAlgebra algebra = gp.ToAlgebra(); Assert.IsInstanceOf(typeof(IJoin), algebra); IJoin join = (IJoin)algebra; Assert.IsInstanceOf(typeof(Graph), join.Lhs); Graph g = (Graph)join.Lhs; Assert.IsInstanceOf(typeof(IBgp), g.InnerAlgebra); Assert.IsInstanceOf(typeof(Bindings), join.Rhs); }
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; } }
public void SparqlGraphPatternToAlgebra5() { GraphPattern gp = new GraphPattern(); gp.IsGraph = true; gp.GraphSpecifier = new VariableToken("g", 0, 0, 1); gp.AddInlineData(new BindingsPattern()); ISparqlAlgebra algebra = gp.ToAlgebra(); Assert.IsAssignableFrom <IJoin>(algebra); IJoin join = (IJoin)algebra; Assert.IsType <Graph>(join.Lhs); Graph g = (Graph)join.Lhs; Assert.IsAssignableFrom <IBgp>(g.InnerAlgebra); Assert.IsAssignableFrom <Bindings>(join.Rhs); }
public void SparqlGraphPatternToAlgebra9() { GraphPattern gp = new GraphPattern(); gp.IsGraph = true; gp.GraphSpecifier = new VariableToken("g", 0, 0, 1); ISparqlAlgebra algebra = gp.ToAlgebra(); Assert.IsType <Graph>(algebra); Graph g = (Graph)algebra; Assert.IsAssignableFrom <IBgp>(g.InnerAlgebra); // Nest in another graph pattern with same specifier but also with another BGP GraphPattern parent = new GraphPattern(); parent.IsGraph = true; parent.GraphSpecifier = gp.GraphSpecifier; parent.AddGraphPattern(gp); ITriplePattern tp = new TriplePattern(new VariablePattern("s"), new VariablePattern("p"), new VariablePattern("o")); parent.AddTriplePattern(tp); // Resulting algebra will keep both graph clauses because of the join algebra = parent.ToAlgebra(); Assert.IsType <Graph>(algebra); g = (Graph)algebra; Assert.IsType <Join>(g.InnerAlgebra); Join join = (Join)g.InnerAlgebra; Assert.IsType <Graph>(join.Lhs); g = (Graph)join.Lhs; Assert.IsAssignableFrom <IBgp>(g.InnerAlgebra); }
private void Validate(GraphPattern pattern) { if (pattern.IsMinus || pattern.InlineData != null || pattern.IsService) { throw new Exception("illegal clauses"); } foreach (var subPattern in pattern.ChildGraphPatterns) { Validate(subPattern); } foreach (var subQueryPattern in pattern.TriplePatterns.OfType <SubQueryPattern>()) { if (!subQueryPattern.Variables.Contains("this")) { throw new Exception("missing projection"); } Validate(subQueryPattern.SubQuery.RootGraphPattern); } }
/// <summary> /// Tries to place filters at the earliest point possible i.e. the first point after which all required variables have occurred /// </summary> /// <param name="gp">Graph Pattern</param> /// <param name="filter">Filter to place</param> /// <returns></returns> private bool TryPlaceFilter(GraphPattern gp, ISparqlFilter filter) { // Firstly we need to find out what variables are needed in the Filter List <String> variablesNeeded = filter.Variables.Distinct().ToList(); // Then we need to move through the Triple Patterns and find the first place at which all the // Variables used in the Filter have been used in ordinary Triple Patterns List <String> variablesUsed = new List <string>(); for (int p = 0; p < gp.TriplePatterns.Count; p++) { if (gp.TriplePatterns[p].PatternType == TriplePatternType.Match || gp.TriplePatterns[p].PatternType == TriplePatternType.BindAssignment || gp.TriplePatterns[p].PatternType == TriplePatternType.LetAssignment) { foreach (String var in gp.TriplePatterns[p].Variables) { if (!variablesUsed.Contains(var)) { variablesUsed.Add(var); } } // Have all the Variables we need now been used in a Pattern? if (variablesNeeded.All(v => variablesUsed.Contains(v))) { // We can place this Filter after the Pattern we were just looking at gp.InsertFilter(filter, p + 1); return(true); } } } // If we reach here then this means that all the Variables used in the Filter did not occur // in the Triple Patterns which means they likely occur in child graph patterns (or the query // is malformed). In this case we cannot place the Filter and it has to be applied post-commit // rather than during Triple Pattern execution return(false); }
/// <summary> /// Tries to reorder patterns when the initial ordering is considered poor /// </summary> /// <param name="gp">Graph Pattern</param> /// <param name="desiredVariables">Variables that are desired</param> /// <param name="start">Point at which to start looking for better matches</param> /// <param name="end">Point at which to move the better match to</param> private void TryReorderPatterns(GraphPattern gp, List <String> desiredVariables, int start, int end) { if (end > start) { return; } // Find the first pattern which does contain a pre-existing variable for (int i = start; i < gp.TriplePatterns.Count; i++) { if (gp.TriplePatterns[i].Variables.Any(v => desiredVariables.Contains(v))) { int newEnd = i; desiredVariables.AddRange(gp.TriplePatterns[i].Variables.Where(v => desiredVariables.Contains(v))); while (i > end) { // Swap Patterns around gp.SwapTriplePatterns(i - 1, i); i--; } end = newEnd; } } }
/// <summary> /// Creates a new INSERT command which operates on the Default Graph /// </summary> /// <param name="insertions">Pattern to construct Triples to insert</param> /// <param name="where">Pattern to select data which is then used in evaluating the insertions</param> public InsertCommand(GraphPattern insertions, GraphPattern where) : this(insertions, where, null) { }
internal static INode ToSpinRdf(this GraphPattern pattern, IGraph g, SpinVariableTable varTable) { INode p = g.CreateBlankNode(); INode ps = p; if (pattern.IsExists) { g.Assert(p, RDF.PropertyType, SP.ClassExists); ps = g.CreateBlankNode(); g.Assert(p, SP.PropertyElements, ps); } else if (pattern.IsGraph) { g.Assert(p, RDF.PropertyType, SP.ClassNamedGraph); INode gSpec = pattern.GraphSpecifier.ToSpinRdf(g, varTable); //g.Assert(p, SP.named, gSpec); // TODO check which is right g.Assert(p, SP.PropertyGraphNameNode, gSpec); // TODO check which is right if (gSpec is IBlankNode) { g.Assert(gSpec, SP.PropertyVarName, pattern.GraphSpecifier.Value.Substring(1).ToLiteral(g)); } ps = g.CreateBlankNode(); g.Assert(p, SP.PropertyElements, ps); } else if (pattern.IsMinus) { g.Assert(p, RDF.PropertyType, SP.ClassMinus); ps = g.CreateBlankNode(); g.Assert(p, SP.PropertyElements, ps); } else if (pattern.IsNotExists) { g.Assert(p, RDF.PropertyType, SP.ClassNotExists); ps = g.CreateBlankNode(); g.Assert(p, SP.PropertyElements, ps); } else if (pattern.IsOptional) { g.Assert(p, RDF.PropertyType, SP.ClassOptional); ps = g.CreateBlankNode(); g.Assert(p, SP.PropertyElements, ps); } else if (pattern.IsService) { g.Assert(p, RDF.PropertyType, SP.ClassService); g.Assert(p, SP.PropertyServiceURI, pattern.GraphSpecifier.ToSpinRdf(g, varTable)); ps = g.CreateBlankNode(); g.Assert(p, SP.PropertyElements, ps); } else if (pattern.IsSubQuery) { g.Assert(p, RDF.PropertyType, SP.ClassSubQuery); ps = g.CreateBlankNode(); g.Assert(p, SP.PropertyQuery, ps); } else if (pattern.IsUnion) { g.Assert(p, RDF.PropertyType, SP.ClassUnion); ps = g.CreateBlankNode(); g.Assert(p, SP.PropertyElements, ps); } if (!pattern.IsEmpty) { //First output Triple Patterns for (int i = 0; i < pattern.TriplePatterns.Count; i++) { INode current = pattern.TriplePatterns[i].ToSpinRdf(g, varTable); if (i == 0) { g.Assert(ps, RDF.PropertyFirst, current); } else { INode temp = g.CreateBlankNode(); g.Assert(ps, RDF.PropertyRest, temp); g.Assert(temp, RDF.PropertyFirst, current); ps = temp; } } if (!pattern.HasChildGraphPatterns) { g.Assert(ps, RDF.PropertyRest, RDF.Nil); } } //Then output Graph Patterns if (pattern.HasChildGraphPatterns) { for (int i = 0; i < pattern.ChildGraphPatterns.Count; i++) { INode current = pattern.ChildGraphPatterns[i].ToSpinRdf(g, varTable); if (pattern.TriplePatterns.Count == 0 && i == 0) { g.Assert(ps, RDF.PropertyFirst, current); } else { INode temp = g.CreateBlankNode(); g.Assert(ps, RDF.PropertyRest, temp); g.Assert(temp, RDF.PropertyFirst, current); ps = temp; } } g.Assert(ps, RDF.PropertyRest, RDF.Nil); } return(p); }
/// <summary> /// Creates a new Service clause with the given Endpoint Specifier and Graph Pattern. /// </summary> /// <param name="endpointSpecifier">Endpoint Specifier.</param> /// <param name="pattern">Graph Pattern.</param> /// <param name="silent">Whether Evaluation Errors are suppressed.</param> public Service(IToken endpointSpecifier, GraphPattern pattern, bool silent) { _endpointSpecifier = endpointSpecifier; _pattern = pattern; _silent = silent; }
/// <summary> /// Creates a new Service clause with the given Endpoint Specifier and Graph Pattern. /// </summary> /// <param name="endpointSpecifier">Endpoint Specifier.</param> /// <param name="pattern">Graph Pattern.</param> public Service(IToken endpointSpecifier, GraphPattern pattern) : this(endpointSpecifier, pattern, false) { }
private SparqlUpdateCommand TryParseInsertCommand(SparqlUpdateParserContext context, bool allowData) { List <Uri> usings = new List <Uri>(); List <Uri> usingNamed = new List <Uri>(); IToken next = context.Tokens.Dequeue(); if (allowData) { //We are allowed to have an INSERT DATA command here so check for it if (next.TokenType == Token.DATA) { return(this.TryParseInsertDataCommand(context)); } } else { if (next.TokenType == Token.DATA) { throw ParserHelper.Error("The DATA keyword is not permitted here as this INSERT command forms part of a modification command", next); } } //Get the Modification Template GraphPattern insertions = this.TryParseModifyTemplate(context); //Then we expect a WHERE keyword next = context.Tokens.Dequeue(); if (next.TokenType == Token.USING) { foreach (KeyValuePair <Uri, bool> kvp in this.TryParseUsingStatements(context)) { if (kvp.Value) { usingNamed.Add(kvp.Key); } else { usings.Add(kvp.Key); } } next = context.Tokens.Dequeue(); } if (next.TokenType != Token.WHERE) { throw ParserHelper.Error("Unexpected Token '" + next.GetType().ToString() + "' encountered, expected a WHERE keyword as part of a INSERT command", next); } //Now parse the WHERE pattern SparqlQueryParserContext subContext = new SparqlQueryParserContext(context.Tokens); subContext.Query.BaseUri = context.BaseUri; subContext.Query.NamespaceMap = context.NamespaceMap; subContext.ExpressionParser.NamespaceMap = context.NamespaceMap; subContext.ExpressionParser.ExpressionFactories = context.ExpressionFactories; subContext.ExpressionFactories = context.ExpressionFactories; GraphPattern where = context.QueryParser.TryParseGraphPattern(subContext, context.Tokens.LastTokenType != Token.LEFTCURLYBRACKET); //And finally return the command InsertCommand cmd = new InsertCommand(insertions, where); usings.ForEach(u => cmd.AddUsingUri(u)); usingNamed.ForEach(u => cmd.AddUsingNamedUri(u)); return(cmd); }
private SparqlUpdateCommand TryParseDeleteCommand(SparqlUpdateParserContext context, bool allowData) { IToken next = context.Tokens.Dequeue(); List <Uri> usings = new List <Uri>(); List <Uri> usingNamed = new List <Uri>(); if (allowData) { // We are allowed to have an DELETE DATA command here so check for it if (next.TokenType == Token.DATA) { return(TryParseDeleteDataCommand(context)); } } else { if (next.TokenType == Token.DATA) { throw ParserHelper.Error("The DATA keyword is not permitted here as this INSERT command forms part of a modification command", next); } } if (next.TokenType == Token.WHERE) { // Parse the WHERE pattern which serves as both the selection and deletion pattern in this case context.Tokens.Dequeue(); GraphPattern where = TryParseModifyTemplate(context); // Then return the command return(new DeleteCommand(where, where)); } // Get the Modification Template GraphPattern deletions = TryParseModifyTemplate(context); // Then we expect a WHERE keyword next = context.Tokens.Dequeue(); if (next.TokenType == Token.USING) { foreach (KeyValuePair <Uri, bool> kvp in TryParseUsingStatements(context)) { if (kvp.Value) { usingNamed.Add(kvp.Key); } else { usings.Add(kvp.Key); } } next = context.Tokens.Dequeue(); } if (next.TokenType == Token.WHERE) { // Now parse the WHERE pattern SparqlQueryParserContext subContext = new SparqlQueryParserContext(context.Tokens); subContext.Query.BaseUri = context.BaseUri; subContext.Query.NamespaceMap = context.NamespaceMap; subContext.ExpressionParser.NamespaceMap = context.NamespaceMap; subContext.ExpressionParser.ExpressionFactories = context.ExpressionFactories; subContext.ExpressionFactories = context.ExpressionFactories; subContext.ExpressionParser.QueryParser = context.QueryParser; GraphPattern where = context.QueryParser.TryParseGraphPattern(subContext, context.Tokens.LastTokenType != Token.LEFTCURLYBRACKET); // And finally return the command DeleteCommand cmd = new DeleteCommand(deletions, @where); usings.ForEach(u => cmd.AddUsingUri(u)); usingNamed.ForEach(u => cmd.AddUsingNamedUri(u)); return(cmd); } if (next.TokenType == Token.INSERT) { InsertCommand insertCmd = (InsertCommand)TryParseInsertCommand(context, false); ModifyCommand cmd = new ModifyCommand(deletions, insertCmd.InsertPattern, insertCmd.WherePattern); insertCmd.UsingUris.ToList().ForEach(u => cmd.AddUsingUri(u)); insertCmd.UsingNamedUris.ToList().ForEach(u => cmd.AddUsingNamedUri(u)); return(cmd); } throw ParserHelper.Error("Unexpected Token '" + next.GetType().ToString() + "' encountered, expected a WHERE keyword as part of a DELETE command", next); }
/// <summary> /// Creates a new EXISTS/NOT EXISTS function /// </summary> /// <param name="pattern">Graph Pattern</param> /// <param name="mustExist">Whether this is an EXIST</param> public ExistsFunction(GraphPattern pattern, bool mustExist) { this._pattern = pattern; this._mustExist = mustExist; }
/// <summary> /// Creates a new Graph Pattern Term /// </summary> /// <param name="pattern">Graph Pattern</param> public GraphPatternTerm(GraphPattern pattern) { this._pattern = pattern; }
/// <summary> /// Creates a new DELETE command /// </summary> /// <param name="where">Pattern to construct Triples to delete</param> /// <param name="graphUri">URI of the affected Graph</param> public DeleteCommand(GraphPattern where, Uri graphUri) : this(where, where, graphUri) { }
/// <summary> /// Createa a new DELETE command which operates on the Default Graph /// </summary> /// <param name="where">Pattern to construct Triples to delete</param> public DeleteCommand(GraphPattern where) : this(where, where, null) { }
/// <summary> /// Causes the Graph Pattern to be optimised if it isn't already /// </summary> /// <param name="gp">Graph Pattern</param> /// <param name="variables">Variables that have occurred prior to this Pattern</param> public void Optimise(GraphPattern gp, IEnumerable <String> variables) { // Our Variables is initially only those in our Triple Patterns since // anything else is considered to be out of scope List <String> ourVariables = (from tp in gp.TriplePatterns from v in tp.Variables select v).Distinct().ToList(); // Start by sorting the Triple Patterns in the list according to the ranking function gp.TriplePatterns.Sort(GetRankingComparer()); // Apply reordering unless an optimiser has chosen to disable it if (ShouldReorder) { if (gp.TriplePatterns.Count > 0) { // After we sort which gives us a rough optimisation we then may want to reorder // based on the Variables that occurred previous to us OR if we're the Root Graph Pattern if (!variables.Any()) { // Optimise this Graph Pattern // No previously occurring variables so must be the first Graph Pattern if (gp.TriplePatterns.Count > 1) { HashSet <String> currVariables = new HashSet <String>(); gp.TriplePatterns[0].Variables.ForEach(v => currVariables.Add(v)); for (int i = 1; i < gp.TriplePatterns.Count - 1; i++) { if (currVariables.Count == 0) { gp.TriplePatterns[i].Variables.ForEach(v => currVariables.Add(v)); continue; } else if (currVariables.IsDisjoint(gp.TriplePatterns[i].Variables)) { TryReorderPatterns(gp, currVariables.ToList(), i + 1, i); gp.TriplePatterns[i].Variables.ForEach(v => currVariables.Add(v)); } else { gp.TriplePatterns[i].Variables.ForEach(v => currVariables.Add(v)); } } } } else { // Optimise this Graph Pattern based on previously occurring variables if (gp.TriplePatterns.Count > 1 && !gp.TriplePatterns[0].Variables.Any(v => variables.Contains(v)) && variables.Intersect(ourVariables).Any()) { TryReorderPatterns(gp, variables.ToList(), 1, 0); } else if (gp.TriplePatterns.Count > 2) { // In the case where there are more than 2 patterns then we can try and reorder these // in order to further optimise the pattern TryReorderPatterns(gp, gp.TriplePatterns[0].Variables, 2, 1); } } } } if (ShouldPlaceAssignments) { // First we need to place Assignments (LETs) in appropriate places within the Pattern // This happens before Filter placement since Filters may use variables assigned to in LETs if (gp.UnplacedAssignments.Any()) { // Need to ensure that we sort Assignments // This way those that use fewer variables get placed first List <IAssignmentPattern> ps = gp.UnplacedAssignments.OrderBy(x => x).ToList(); // This next bit goes in a do loop as we want to keep attempting to place assignments while // we are able to do so. If the count of unplaced assignments has decreased but is not // zero it may be that we were unable to place some patterns as they relied on variables // assigned in other LETs which weren't placed when we attempted to place them // When we reach the point where no further placements have occurred or all assignments // are placed we stop trying to place assignments int c; do { c = ps.Count; int i = 0; while (i < ps.Count) { if (TryPlaceAssignment(gp, ps[i])) { // Remove from Unplaced Assignments since it's been successfully placed in the Triple Patterns // Don't increment the counter since the next Assignment is now at the index we're already at ps.RemoveAt(i); } else { // Unable to place so increment counter i++; } } } while (c > ps.Count && ps.Count > 0); } } // Regardless of what we've placed already we now place all remaining assignments // foreach (IAssignmentPattern assignment in gp.UnplacedAssignments.ToList()) // { // gp.InsertAssignment(assignment, gp.TriplePatterns.Count); // } if (ShouldPlaceFilters) { // Then we need to place the Filters in appropriate places within the Pattern if (gp.UnplacedFilters.Any()) { if (gp.TriplePatterns.Count == 0) { // Where there are no Triple Patterns the Graph Pattern just contains this Filter and possibly some // child Graph Patterns. In such a case then we shouldn't place the Filters } else { if (ShouldSplitFilters) { // See whether we can split any/all of the Unplaced Filters List <ISparqlFilter> fs = gp.UnplacedFilters.ToList(); for (int i = 0; i < fs.Count; i++) { ISparqlFilter f = fs[i]; if (f.Expression is AndExpression) { // Split the And // Note that multiple nested And's are handled by the fact that we will continue working through the list until it is finished UnaryExpressionFilter lhs = new UnaryExpressionFilter(f.Expression.Arguments.First()); UnaryExpressionFilter rhs = new UnaryExpressionFilter(f.Expression.Arguments.Last()); fs.RemoveAt(i); fs.Add(lhs); fs.Add(rhs); } } // Finally we need to ensure the Unplaced Filters list is appropriately updated gp.ResetFilters(fs); } foreach (ISparqlFilter f in gp.UnplacedFilters.ToList()) { TryPlaceFilter(gp, f); } } } } // Finally optimise the Child Graph Patterns foreach (GraphPattern cgp in gp.ChildGraphPatterns) { // At each point the variables that have occurred are those in the Triple Patterns and // those in previous Graph Patterns cgp.Optimise(this, ourVariables); ourVariables.AddRange(cgp.Variables); } // Note: Any remaining Unplaced Filters/Assignments are OK since the ToAlgebra() method of a GraphPattern // will take care of placing these appropriately }
private SparqlUpdateCommand TryParseInsertDataCommand(SparqlUpdateParserContext context) { InsertDataCommand cmd; SparqlQueryParserContext subContext = new SparqlQueryParserContext(context.Tokens); subContext.Query.BaseUri = context.BaseUri; subContext.Query.NamespaceMap = context.NamespaceMap; subContext.ExpressionParser.NamespaceMap = context.NamespaceMap; subContext.ExpressionParser.ExpressionFactories = context.ExpressionFactories; subContext.ExpressionFactories = context.ExpressionFactories; subContext.CheckBlankNodeScope = false; GraphPattern gp = context.QueryParser.TryParseGraphPattern(subContext, context.Tokens.LastTokenType != Token.LEFTCURLYBRACKET); //Validate use of Blank Nodes in INSERT DATA, same BNode MAY be used within different graph patterns in a single command //though each represents a fresh blank node //The same BNode MAY NOT be used across separate commands if (context.DataBNodes.Count == 0) { //First INSERT DATA so simply register all the BNodes foreach (String var in gp.Variables.Where(v => v.StartsWith("_:"))) { context.DataBNodes.Add(var); } } else { //Some INSERT DATA commands have already occurred, validate that newly introduced variables are not already present foreach (String var in gp.Variables.Where(v => v.StartsWith("_:")).Distinct()) { if (context.DataBNodes.Contains(var)) { throw new RdfParseException("An INSERT DATA command used the BNode " + var + " which has been used in previous INSERT DATA commands and is not permitted per Section 19.6 of the specification"); } else { context.DataBNodes.Add(var); } } } //Validate that the Graph Pattern is simple //Check it doesn't contain anything other than Triple Patterns or if it does it just contains a single GRAPH Pattern if (gp.IsFiltered) { throw new RdfParseException("A FILTER Clause cannot occur in a INSERT DATA Command"); } else if (gp.IsOptional) { throw new RdfParseException("An OPTIONAL Clause cannot occur in a INSERT DATA Command"); } else if (gp.IsUnion) { throw new RdfParseException("A UNION Clause cannot occur in a INSERT DATA Command"); } else if (gp.HasChildGraphPatterns) { if (!gp.ChildGraphPatterns.All(p => (p.IsGraph && p.GraphSpecifier.TokenType != Token.VARIABLE) || (!p.IsExists && !p.IsMinus && !p.IsNotExists && !p.IsOptional && !p.IsOptional && !p.IsService && !p.IsSubQuery && !p.IsUnion && !p.IsGraph))) { throw new RdfParseException("An INSERT DATA Command may only contain a combination of Triple Patterns and GRAPH clauses, GRAPH clauses must specify a Graph URI"); } else if (gp.ChildGraphPatterns.Any(p => p.HasChildGraphPatterns)) { throw new RdfParseException("An INSERT DATA Command may not contain nested Graph Patterns"); } else if (gp.ChildGraphPatterns.Count == 1 && gp.ChildGraphPatterns[0].IsGraph && gp.TriplePatterns.Count == 0) { cmd = new InsertDataCommand(gp.ChildGraphPatterns[0]); } else if (gp.HasChildGraphPatterns) { cmd = new InsertDataCommand(gp); } else { throw new RdfParseException("Nested Graph Patterns cannot occur in a INSERT DATA Command"); } } else { //OK cmd = new InsertDataCommand(gp); } return(cmd); }
/// <summary> /// Creates a new Graph Pattern Term. /// </summary> /// <param name="pattern">Graph Pattern.</param> public GraphPatternTerm(GraphPattern pattern) { _pattern = pattern; }
/// <summary> /// Formats a Graph Pattern in nicely formatted SPARQL syntax /// </summary> /// <param name="gp">Graph Pattern</param> /// <returns></returns> public virtual String Format(GraphPattern gp) { if (gp == null) { throw new RdfOutputException("Cannot format a null Graph Pattern as a String"); } StringBuilder output = new StringBuilder(); if (gp.IsUnion) { for (int i = 0; i < gp.ChildGraphPatterns.Count; i++) { GraphPattern cgp = gp.ChildGraphPatterns[i]; if (cgp.HasModifier) { String formatted = this.Format(cgp); formatted = formatted.TrimEnd(new char[] { '\n', '\r' }); if (formatted.Contains("\n")) { output.AppendLine("{"); output.AppendLineIndented(formatted, 2); output.AppendLine("}"); } else { output.AppendLine("{ " + formatted + "}"); } } else { output.AppendLine(this.Format(cgp)); } if (i < gp.ChildGraphPatterns.Count - 1) { output.AppendLine("UNION"); } } return(output.ToString()); } else if (gp.IsGraph || gp.IsService) { if (gp.IsGraph) { output.Append("GRAPH "); } else { output.Append("SERVICE "); if (gp.IsSilent) { output.Append("SILENT "); } } switch (gp.GraphSpecifier.TokenType) { case Token.QNAME: try { String uri = Tools.ResolveQName(gp.GraphSpecifier.Value, this._qnameMapper, this._tempBaseUri); //If the QName resolves OK in the context of the Namespace Map we're using to format this then we //can print the QName as-is output.Append(gp.GraphSpecifier.Value); } catch { //If the QName fails to resolve then can't format in the context throw new RdfOutputException("Cannot format the Graph/Service Specifier QName " + gp.GraphSpecifier.Value + " as the Namespace Mapper in use for this Formatter cannot resolve the QName"); } break; case Token.URI: output.Append('<'); output.Append(this.FormatUri(gp.GraphSpecifier.Value)); output.Append('>'); break; case Token.VARIABLE: default: output.Append(gp.GraphSpecifier.Value); break; } output.Append(' '); } else if (gp.IsSubQuery) { output.AppendLine("{"); output.AppendLineIndented(this.Format(((ISubQueryPattern)gp.TriplePatterns[0]).SubQuery), 2); output.AppendLine("}"); return(output.ToString()); } else if (gp.IsOptional) { output.Append("OPTIONAL "); } else if (gp.IsExists) { output.Append("EXISTS "); } else if (gp.IsNotExists) { output.Append("NOT EXISTS "); } else if (gp.IsMinus) { output.Append("MINUS "); } if (gp.TriplePatterns.Count > 1 || gp.HasChildGraphPatterns || (gp.TriplePatterns.Count <= 1 && gp.Filter != null) || gp.UnplacedAssignments.Count() > 0 || gp.UnplacedFilters.Count() > 0 || gp.HasInlineData) { output.AppendLine("{"); foreach (ITriplePattern tp in gp.TriplePatterns) { output.AppendLineIndented(this.Format(tp), 2); } foreach (IAssignmentPattern ap in gp.UnplacedAssignments) { output.AppendLineIndented(this.Format(ap), 2); } if (gp.HasInlineData) { output.AppendLineIndented(this.FormatInlineData(gp.InlineData), 2); } foreach (GraphPattern child in gp.ChildGraphPatterns) { output.AppendLineIndented(this.Format(child), 2); } foreach (ISparqlFilter fp in gp.UnplacedFilters) { output.AppendIndented("FILTER(", 2); output.Append(this.FormatExpression(fp.Expression)); output.AppendLine(")"); } output.Append("}"); } else if (gp.TriplePatterns.Count == 0) { if (gp.Filter != null) { if (gp.HasInlineData) { output.AppendLineIndented("{", 2); output.AppendLineIndented(this.FormatInlineData(gp.InlineData), 4); output.AppendLineIndented("FILTER (" + this.FormatExpression(gp.Filter.Expression) + ")", 4); output.AppendLineIndented("}", 2); } else { output.AppendIndented("{ FILTER(", 2); output.Append(this.FormatExpression(gp.Filter.Expression)); output.AppendLine(") }"); } } else if (gp.HasInlineData) { output.AppendLineIndented("{", 2); output.AppendLineIndented(this.FormatInlineData(gp.InlineData), 4); output.AppendLineIndented("}", 2); } else { output.Append("{ }"); } } else if (gp.HasInlineData) { output.AppendLineIndented("{", 2); output.AppendLineIndented(this.Format(gp.TriplePatterns[0]), 4); output.AppendLineIndented(this.FormatInlineData(gp.InlineData), 4); output.AppendLineIndented("}", 2); } else { output.Append("{ "); output.Append(this.Format(gp.TriplePatterns[0])); output.Append(" }"); } return(output.ToString()); }
public void AppendTo(GraphPattern graphPattern) { graphPattern.AddInlineData(_bindingsPattern); }
/// <summary> /// Creates a new Graph Pattern Expression /// </summary> /// <param name="pattern">Graph Pattern</param> public GraphPatternExpressionTerm(GraphPattern pattern) { this._pattern = pattern; }
/// <summary> /// Creates a new INSERT/DELETE command which operates on the Default Graph. /// </summary> /// <param name="deletions">Pattern to construct Triples to delete.</param> /// <param name="insertions">Pattern to construct Triples to insert.</param> /// <param name="where">Pattern to select data which is then used in evaluating the insertions and deletions.</param> public ModifyCommand(GraphPattern deletions, GraphPattern insertions, GraphPattern where) : this(deletions, insertions, where, null) { }