/// <summary> /// Returns the Graph which is the Result of the Describe Query by computing the Concise Bounded Description for all Results /// </summary> /// <param name="context">SPARQL Evaluation Context</param> /// <returns></returns> public override IGraph Describe(SparqlEvaluationContext context) { //Get a new empty Graph and import the Base Uri and Namespace Map of the Query Graph g = new Graph(); g.BaseUri = context.Query.BaseUri; g.NamespaceMap.Import(context.Query.NamespaceMap); //Build a list of INodes to describe List<INode> nodes = new List<INode>(); foreach (IToken t in context.Query.DescribeVariables) { switch (t.TokenType) { case Token.QNAME: case Token.URI: //Resolve Uri/QName nodes.Add(new UriNode(g, new Uri(Tools.ResolveUriOrQName(t, g.NamespaceMap, g.BaseUri)))); break; case Token.VARIABLE: //Get Variable Values String var = t.Value.Substring(1); if (context.OutputMultiset.ContainsVariable(var)) { foreach (Set s in context.OutputMultiset.Sets) { INode temp = s[var]; if (temp != null) nodes.Add(temp); } } break; default: throw new RdfQueryException("Unexpected Token '" + t.GetType().ToString() + "' in DESCRIBE Variables list"); } } //Rewrite Blank Node IDs for DESCRIBE Results Dictionary<String, INode> bnodeMapping = new Dictionary<string, INode>(); //Get Triples for this Subject foreach (INode n in nodes) { //Get Triples where the Node is the Subject foreach (Triple t in context.Data.GetTriplesWithSubject(n)) { g.Assert(this.RewriteDescribeBNodes(t, bnodeMapping, g)); } //Get Triples where the Node is the Object foreach (Triple t in context.Data.GetTriplesWithObject(n)) { g.Assert(this.RewriteDescribeBNodes(t, bnodeMapping, g)); } } //Return the Graph g.BaseUri = null; return g; }
/// <summary> /// Processes a Graph /// </summary> /// <param name="graph">Graph</param> /// <param name="context">SPARQL Evaluation Context</param> public virtual BaseMultiset ProcessGraph(Algebra.Graph graph, SparqlEvaluationContext context) { if (context == null) { context = this.GetContext(); } return(graph.Evaluate(context)); }
private ISparqlDataset GetTestData() { InMemoryDataset dataset = new InMemoryDataset(); Graph g = new Graph(); FileLoader.Load(g, "InferenceTest.ttl"); dataset.AddGraph(g); return dataset; }
private void EnsureTestData() { if (this._data == null) { TripleStore store = new TripleStore(); Graph g = new Graph(); g.LoadFromEmbeddedResource("VDS.RDF.Configuration.configuration.ttl"); store.Add(g); this._data = new InMemoryDataset(store); } }
/// <summary> /// Returns the Graph which is the merge of all the Graphs which are named with URIs contained in the Results /// </summary> /// <param name="context">Evaluation Context</param> /// <returns></returns> public IGraph Describe(SparqlEvaluationContext context) { //Get a new empty Graph and import the Base Uri and Namespace Map of the Query Graph g = new Graph(); g.BaseUri = context.Query.BaseUri; g.NamespaceMap.Import(context.Query.NamespaceMap); //Build a list of INodes to describe List<INode> nodes = new List<INode>(); foreach (IToken t in context.Query.DescribeVariables) { switch (t.TokenType) { case Token.QNAME: case Token.URI: //Resolve Uri/QName nodes.Add(new UriNode(g, new Uri(Tools.ResolveUriOrQName(t, g.NamespaceMap, g.BaseUri)))); break; case Token.VARIABLE: //Get Variable Values String var = t.Value.Substring(1); if (context.OutputMultiset.ContainsVariable(var)) { foreach (Set s in context.OutputMultiset.Sets) { INode temp = s[var]; if (temp != null) nodes.Add(temp); } } break; default: throw new RdfQueryException("Unexpected Token '" + t.GetType().ToString() + "' in DESCRIBE Variables list"); } } foreach (INode n in nodes) { if (n.NodeType == NodeType.Uri) { IUriNode u = (IUriNode)n; if (context.Data.HasGraph(u.Uri)) { g.Merge(context.Data[u.Uri]); } } } return g; }
/// <summary> /// Evaluates the Command in the given Context /// </summary> /// <param name="context">Evaluation Context</param> public override void Evaluate(SparqlUpdateEvaluationContext context) { bool datasetOk = false; bool defGraphOk = false; try { //First evaluate the WHERE pattern to get the affected bindings ISparqlAlgebra where = this._wherePattern.ToAlgebra(); if (context.Commands != null) { where = context.Commands.ApplyAlgebraOptimisers(where); } //Set Active Graph for the WHERE //Don't bother if there are USING URIs as these would override any Active Graph we set here //so we can save ourselves the effort of doing this if (!this.UsingUris.Any()) { if (this._graphUri != null) { context.Data.SetActiveGraph(this._graphUri); defGraphOk = true; } else { context.Data.SetActiveGraph((Uri)null); defGraphOk = true; } } //We need to make a dummy SparqlQuery object since if the Command has used any //USING NAMEDs along with GRAPH clauses then the algebra needs to have the //URIs available to it which it gets from the Query property of the Context //object SparqlQuery query = new SparqlQuery(); foreach (Uri u in this.UsingUris) { query.AddDefaultGraph(u); } foreach (Uri u in this.UsingNamedUris) { query.AddNamedGraph(u); } SparqlEvaluationContext queryContext = new SparqlEvaluationContext(query, context.Data, context.QueryProcessor); if (this.UsingUris.Any()) { //If there are USING URIs set the Active Graph to be formed of the Graphs with those URIs context.Data.SetActiveGraph(this._usingUris); datasetOk = true; } BaseMultiset results = queryContext.Evaluate(where); if (this.UsingUris.Any()) { //If there are USING URIs reset the Active Graph afterwards //Also flag the dataset as no longer being OK as this flag is used in the finally //block to determine whether the Active Graph needs resetting which it may do if the //evaluation of the context.Data.ResetActiveGraph(); datasetOk = false; } //Reset Active Graph for the WHERE if (defGraphOk) { context.Data.ResetActiveGraph(); defGraphOk = false; } //Get the Graph to which we are deleting and inserting IGraph g; if (context.Data.HasGraph(this._graphUri)) { g = context.Data.GetModifiableGraph(this._graphUri); } else { g = null; } //Delete the Triples for each Solution List<Triple> deletedTriples = new List<Triple>(); foreach (ISet s in queryContext.OutputMultiset.Sets) { try { //If the Default Graph is non-existent then Deletions have no effect on it if (g != null) { ConstructContext constructContext = new ConstructContext(g, s, true); foreach (IConstructTriplePattern p in this._deletePattern.TriplePatterns.OfType<IConstructTriplePattern>()) { try { deletedTriples.Add(p.Construct(constructContext)); } catch (RdfQueryException) { //If we get an error here then we couldn't construct a specific //triple so we continue anyway } } g.Retract(deletedTriples); } } catch (RdfQueryException) { //If we get an error here this means we couldn't construct for this solution so the //solution is ignored for this graph } //Triples from GRAPH clauses foreach (GraphPattern gp in this._deletePattern.ChildGraphPatterns) { deletedTriples.Clear(); try { String graphUri; switch (gp.GraphSpecifier.TokenType) { case Token.URI: graphUri = gp.GraphSpecifier.Value; break; case Token.VARIABLE: if (s.ContainsVariable(gp.GraphSpecifier.Value)) { INode temp = s[gp.GraphSpecifier.Value.Substring(1)]; if (temp == null) { //If the Variable is not bound then skip continue; } else if (temp.NodeType == NodeType.Uri) { graphUri = temp.ToSafeString(); } else { //If the Variable is not bound to a URI then skip continue; } } else { //If the Variable is not bound for this solution then skip continue; } break; default: //Any other Graph Specifier we have to ignore this solution continue; } //If the Dataset doesn't contain the Graph then no need to do the Deletions if (!context.Data.HasGraph(UriFactory.Create(graphUri))) continue; //Do the actual Deletions IGraph h = context.Data.GetModifiableGraph(UriFactory.Create(graphUri)); ConstructContext constructContext = new ConstructContext(h, s, true); foreach (IConstructTriplePattern p in gp.TriplePatterns.OfType<IConstructTriplePattern>()) { try { deletedTriples.Add(p.Construct(constructContext)); } catch (RdfQueryException) { //If we get an error here then we couldn't construct a specific triple //so we continue anyway } } h.Retract(deletedTriples); } catch (RdfQueryException) { //If we get an error here this means we couldn't construct for this solution so the //solution is ignore for this graph } } } //Insert the Triples for each Solution foreach (ISet s in queryContext.OutputMultiset.Sets) { List<Triple> insertedTriples = new List<Triple>(); try { ConstructContext constructContext = new ConstructContext(g, s, true); foreach (IConstructTriplePattern p in this._insertPattern.TriplePatterns.OfType<IConstructTriplePattern>()) { try { insertedTriples.Add(p.Construct(constructContext)); } catch (RdfQueryException) { //If we get an error here then we couldn't construct a specific triple //so we continue anyway } } g.Assert(insertedTriples); } catch (RdfQueryException) { //If we get an error here this means we couldn't construct for this solution so the //solution is ignored for this graph } //Triples from GRAPH clauses foreach (GraphPattern gp in this._insertPattern.ChildGraphPatterns) { insertedTriples.Clear(); try { String graphUri; switch (gp.GraphSpecifier.TokenType) { case Token.URI: graphUri = gp.GraphSpecifier.Value; break; case Token.VARIABLE: if (s.ContainsVariable(gp.GraphSpecifier.Value)) { INode temp = s[gp.GraphSpecifier.Value.Substring(1)]; if (temp == null) { //If the Variable is not bound then skip continue; } else if (temp.NodeType == NodeType.Uri) { graphUri = temp.ToSafeString(); } else { //If the Variable is not bound to a URI then skip continue; } } else { //If the Variable is not bound for this solution then skip continue; } break; default: //Any other Graph Specifier we have to ignore this solution continue; } //Ensure the Graph we're inserting to exists in the dataset creating it if necessary IGraph h; Uri destUri = UriFactory.Create(graphUri); if (context.Data.HasGraph(destUri)) { h = context.Data.GetModifiableGraph(destUri); } else { h = new Graph(); h.BaseUri = destUri; context.Data.AddGraph(h); h = context.Data.GetModifiableGraph(destUri); } //Do the actual Insertions ConstructContext constructContext = new ConstructContext(h, s, true); foreach (IConstructTriplePattern p in gp.TriplePatterns.OfType<IConstructTriplePattern>()) { try { insertedTriples.Add(p.Construct(constructContext)); } catch (RdfQueryException) { //If we get an error here this means we couldn't construct a specific //triple so we continue anyway } } h.Assert(insertedTriples); } catch (RdfQueryException) { //If we get an error here this means we couldn't construct for this solution so the //solution is ignored for this graph } } } } finally { //If the Dataset was set and an error occurred in doing the WHERE clause then //we'll need to Reset the Active Graph if (datasetOk) context.Data.ResetActiveGraph(); if (defGraphOk) context.Data.ResetActiveGraph(); } }
/// <summary> /// Processes a DROP command /// </summary> /// <param name="cmd">Drop Command</param> public void ProcessDropCommand(DropCommand cmd) { if (this._manager is IUpdateableGenericIOManager) { ((IUpdateableGenericIOManager)this._manager).Update(cmd.ToString()); } else { try { Graph g; switch (cmd.Mode) { case ClearMode.Graph: case ClearMode.Default: if (this._manager.DeleteSupported) { //If available use DeleteGraph() this._manager.DeleteGraph(cmd.TargetUri); } else if ((cmd.TargetUri == null && (this._manager.IOBehaviour & IOBehaviour.OverwriteDefault) != 0) || (cmd.TargetUri != null && (this._manager.IOBehaviour & IOBehaviour.OverwriteNamed) != 0)) { //Can approximate by saving an empty Graph over the existing Graph g = new Graph(); g.BaseUri = cmd.TargetUri; this._manager.SaveGraph(g); } else if (this._manager.UpdateSupported && (this._manager.IOBehaviour & IOBehaviour.CanUpdateDeleteTriples) != 0) { //Can approximate by loading the Graph and then deleting all Triples from it g = new NonIndexedGraph(); this._manager.LoadGraph(g, cmd.TargetUri); this._manager.UpdateGraph(cmd.TargetUri, null, g.Triples); } else { throw new SparqlUpdateException("Unable to evaluate a DROP command as the underlying store does not provide appropriate IO Behaviour to approximate this command"); } break; case ClearMode.All: case ClearMode.Named: if (this._manager.ListGraphsSupported) { List<Uri> graphs = this._manager.ListGraphs().ToList(); foreach (Uri u in graphs) { if (this._manager.DeleteSupported) { //If available use DeleteGraph() this._manager.DeleteGraph(u); } else if ((u == null && (this._manager.IOBehaviour & IOBehaviour.OverwriteDefault) != 0) || (u != null && (this._manager.IOBehaviour & IOBehaviour.OverwriteNamed) != 0)) { //Can approximate by saving an empty Graph over the existing Graph g = new Graph(); g.BaseUri = u; this._manager.SaveGraph(g); } else if (this._manager.UpdateSupported && (this._manager.IOBehaviour & IOBehaviour.CanUpdateDeleteTriples) != 0) { //Can approximate by loading the Graph and then deleting all Triples from it g = new NonIndexedGraph(); this._manager.LoadGraph(g, u); this._manager.UpdateGraph(u, null, g.Triples); } else { throw new SparqlUpdateException("Unable to evaluate a DROP command as the underlying store does not provide appropriate IO Behaviour to approximate this command"); } } } else { throw new NotSupportedException("The Generic Update processor does not support this form of the DROP command"); } break; } } catch { if (!cmd.Silent) throw; } } }
/// <summary> /// Processes an INSERT command /// </summary> /// <param name="cmd">Insert Command</param> /// <remarks> /// <para> /// <strong>Note:</strong> The underlying manager must implement the <see cref="IQueryableGenericIOManager">IQueryableGenericIOManager</see> interface in order for INSERT commands to be processed /// </para> /// </remarks> public void ProcessInsertCommand(InsertCommand cmd) { if (this._manager is IUpdateableGenericIOManager) { ((IUpdateableGenericIOManager)this._manager).Update(cmd.ToString()); } else { if (this._manager is IQueryableGenericIOManager) { //Check IO Behaviour //For a insert we either need the ability to Update Add Triples or to Overwrite Graphs //Firstly check behaviour persuant to default graph if applicable if (cmd.InsertPattern.TriplePatterns.OfType<IConstructTriplePattern>().Any()) { //Must support notion of default graph if ((this._manager.IOBehaviour & IOBehaviour.HasDefaultGraph) == 0) throw new SparqlUpdateException("The underlying store does not support the notion of an explicit unnamed Default Graph required to process this command"); //Must allow either OverwriteDefault or CanUpdateAddTriples if ((this._manager.IOBehaviour & IOBehaviour.CanUpdateAddTriples) == 0 && (this._manager.IOBehaviour & IOBehaviour.OverwriteDefault) == 0) throw new SparqlUpdateException("The underlying store does not support the required IO Behaviour to implement this command"); } //Then check behaviour persuant to named graphs if applicable if (cmd.InsertPattern.HasChildGraphPatterns) { //Must support named graphs if ((this._manager.IOBehaviour & IOBehaviour.HasNamedGraphs) == 0) throw new SparqlUpdateException("The underlying store does not support the notion of named graphs required to process this command"); //Must allow either CanUpdateAddTriples or OverwriteNamed if ((this._manager.IOBehaviour & IOBehaviour.CanUpdateAddTriples) == 0 && (this._manager.IOBehaviour & IOBehaviour.OverwriteNamed) == 0) throw new SparqlUpdateException("The underlying store does not support the required IO Behaviour to implement this command"); } //First build and make the query to get a Result Set String queryText = "SELECT * WHERE " + cmd.WherePattern.ToString(); SparqlQueryParser parser = new SparqlQueryParser(); SparqlQuery query = parser.ParseFromString(queryText); if (cmd.GraphUri != null && !cmd.UsingUris.Any()) query.AddDefaultGraph(cmd.GraphUri); foreach (Uri u in cmd.UsingUris) { query.AddDefaultGraph(u); } foreach (Uri u in cmd.UsingNamedUris) { query.AddNamedGraph(u); } Object results = ((IQueryableGenericIOManager)this._manager).Query(query.ToString()); if (results is SparqlResultSet) { //Now need to transform the Result Set back to a Multiset Multiset mset = new Multiset((SparqlResultSet)results); //Generate the Triples for each Solution List<Triple> insertedTriples = new List<Triple>(); Dictionary<String, List<Triple>> insertedGraphTriples = new Dictionary<string, List<Triple>>(); foreach (ISet s in mset.Sets) { List<Triple> tempInsertedTriples = new List<Triple>(); try { ConstructContext context = new ConstructContext(null, s, true); foreach (IConstructTriplePattern p in cmd.InsertPattern.TriplePatterns.OfType<IConstructTriplePattern>()) { try { tempInsertedTriples.Add(p.Construct(context)); } catch (RdfQueryException) { //If we get an error here then it means we couldn't construct a specific //triple so we continue anyway } } insertedTriples.AddRange(tempInsertedTriples); } catch (RdfQueryException) { //If we get an error here this means we couldn't construct for this solution so the //solution is ignore for this graph } //Triples from GRAPH clauses foreach (GraphPattern gp in cmd.InsertPattern.ChildGraphPatterns) { tempInsertedTriples.Clear(); try { String graphUri; switch (gp.GraphSpecifier.TokenType) { case Token.URI: graphUri = gp.GraphSpecifier.Value; break; case Token.VARIABLE: if (s.ContainsVariable(gp.GraphSpecifier.Value)) { INode temp = s[gp.GraphSpecifier.Value.Substring(1)]; if (temp == null) { //If the Variable is not bound then skip continue; } else if (temp.NodeType == NodeType.Uri) { graphUri = temp.ToSafeString(); } else { //If the Variable is not bound to a URI then skip continue; } } else { //If the Variable is not bound for this solution then skip continue; } break; default: //Any other Graph Specifier we have to ignore this solution continue; } if (!insertedGraphTriples.ContainsKey(graphUri)) insertedGraphTriples.Add(graphUri, new List<Triple>()); ConstructContext context = new ConstructContext(null, s, true); foreach (IConstructTriplePattern p in gp.TriplePatterns.OfType<IConstructTriplePattern>()) { try { tempInsertedTriples.Add(p.Construct(context)); } catch (RdfQueryException) { //If we get an error here then it means we couldn't construct a specific //triple so we continue anyway } } insertedGraphTriples[graphUri].AddRange(tempInsertedTriples); } catch (RdfQueryException) { //If we get an error here this means we couldn't construct for this solution so the //solution is ignore for this graph } } } //Now decide how to apply the update if (this._manager.UpdateSupported) { this._manager.UpdateGraph(cmd.GraphUri, insertedTriples, Enumerable.Empty<Triple>()); foreach (KeyValuePair<String, List<Triple>> graphInsertion in insertedGraphTriples) { this._manager.UpdateGraph(graphInsertion.Key, graphInsertion.Value, Enumerable.Empty<Triple>()); } } else { Graph g = new Graph(); this._manager.LoadGraph(g, cmd.GraphUri); g.Assert(insertedTriples); this._manager.SaveGraph(g); foreach (KeyValuePair<String, List<Triple>> graphInsertion in insertedGraphTriples) { g = new Graph(); this._manager.LoadGraph(g, graphInsertion.Key); g.Assert(graphInsertion.Value); this._manager.SaveGraph(g); } } } else { throw new SparqlUpdateException("Cannot evaluate an INSERT Command as the underlying Store failed to answer the query for the WHERE portion of the command as expected"); } } else { throw new NotSupportedException("INSERT commands are not supported by this Update Processor as the manager for the underlying Store does not provide Query capabilities which are necessary to process this command"); } } }
/// <summary> /// Processes a COPY command /// </summary> /// <param name="cmd">Copy Command</param> public void ProcessCopyCommand(CopyCommand cmd) { if (this._manager is IUpdateableGenericIOManager) { ((IUpdateableGenericIOManager)this._manager).Update(cmd.ToString()); } else { try { Graph source = new Graph(); this._manager.LoadGraph(source, cmd.SourceUri); source.BaseUri = cmd.SourceUri; //If the Manager supports delete ensure the Destination Graph is deleted if (this._manager.DeleteSupported) { try { this._manager.DeleteGraph(cmd.DestinationUri); } catch (Exception ex) { throw new SparqlUpdateException("Unable to process a MOVE command as unable to ensure that the Destination Graph was deleted prior to moving the data from the Source Graph", ex); } } //Load Destination Graph and ensure it is empty Graph dest = new Graph(); this._manager.LoadGraph(dest, cmd.DestinationUri); dest.BaseUri = cmd.DestinationUri; dest.Clear(); //Transfer the data and update both the Graphs dest.Merge(source); this._manager.SaveGraph(dest); } catch { if (!cmd.Silent) throw; } } }
/// <summary> /// Processes a DELETE DATA command /// </summary> /// <param name="cmd">DELETE Data Command</param> public void ProcessDeleteDataCommand(DeleteDataCommand cmd) { if (this._manager is IUpdateableGenericIOManager) { ((IUpdateableGenericIOManager)this._manager).Update(cmd.ToString()); } else { //Check IO Behaviour //For a delete we either need the ability to Update Delete Triples or to Overwrite Graphs //Firstly check behaviour persuant to default graph if applicable if (cmd.DataPattern.TriplePatterns.OfType<IConstructTriplePattern>().Any()) { //Must support notion of default graph if ((this._manager.IOBehaviour & IOBehaviour.HasDefaultGraph) == 0) throw new SparqlUpdateException("The underlying store does not support the notion of an explicit unnamed Default Graph required to process this command"); //Must allow either OverwriteDefault or CanUpdateDeleteTriples if ((this._manager.IOBehaviour & IOBehaviour.CanUpdateDeleteTriples) == 0 && (this._manager.IOBehaviour & IOBehaviour.OverwriteDefault) == 0) throw new SparqlUpdateException("The underlying store does not support the required IO Behaviour to implement this command"); } //Then check behaviour persuant to named graphs if applicable if (cmd.DataPattern.HasChildGraphPatterns) { //Must support named graphs if ((this._manager.IOBehaviour & IOBehaviour.HasNamedGraphs) == 0) throw new SparqlUpdateException("The underlying store does not support the notion of named graphs required to process this command"); //Must allow either CanUpdateDeleteTriples or OverwriteNamed if ((this._manager.IOBehaviour & IOBehaviour.CanUpdateDeleteTriples) == 0 && (this._manager.IOBehaviour & IOBehaviour.OverwriteNamed) == 0) throw new SparqlUpdateException("The underlying store does not support the required IO Behaviour to implement this command"); } //Split the Pattern into the set of Graph Patterns List<GraphPattern> patterns = new List<GraphPattern>(); if (cmd.DataPattern.IsGraph) { patterns.Add(cmd.DataPattern); } else if (cmd.DataPattern.TriplePatterns.Count > 0 || cmd.DataPattern.HasChildGraphPatterns) { if (cmd.DataPattern.TriplePatterns.Count > 0) { patterns.Add(new GraphPattern()); cmd.DataPattern.TriplePatterns.ForEach(tp => patterns[0].AddTriplePattern(tp)); } cmd.DataPattern.ChildGraphPatterns.ForEach(gp => patterns.Add(gp)); } else { //If no Triple Patterns and No Child Graph Patterns nothing to do return; } foreach (GraphPattern pattern in patterns) { if (!this.IsValidDataPattern(pattern, false)) throw new SparqlUpdateException("Cannot evaluate a DELETE DATA command where any of the Triple Patterns are not concrete triples - variables are not permitted"); Uri graphUri = null; if (pattern.IsGraph) { switch (pattern.GraphSpecifier.TokenType) { case Token.QNAME: throw new NotSupportedException("Graph Specifiers as QNames for DELETE DATA Commands are not supported - please specify an absolute URI instead"); case Token.URI: graphUri = UriFactory.Create(pattern.GraphSpecifier.Value); break; default: throw new SparqlUpdateException("Cannot evaluate an DELETE DATA Command as the Graph Specifier is not a QName/URI"); } } Graph g = new Graph(); if (!this._manager.UpdateSupported) { //If the Graph to be deleted from is empty then can skip as will have no affect on the Graph this._manager.LoadGraph(g, graphUri); if (g.IsEmpty) continue; } //Note that if the Manager supports Triple Level updates we won't load the Graph //so we can't know whether it is empty or not and so can't skip the delete step //Delete the actual Triples INode subj, pred, obj; ConstructContext context = new ConstructContext(g, null, true); foreach (IConstructTriplePattern p in pattern.TriplePatterns.OfType<IConstructTriplePattern>()) { subj = p.Subject.Construct(context); pred = p.Predicate.Construct(context); obj = p.Object.Construct(context); if (!this._manager.UpdateSupported) { //If we don't support update then we'll have loaded the existing graph //so we'll use this to remove the relevant triples to get to the intended state of //the graph g.Retract(new Triple(subj, pred, obj)); } else { //If we do support update then we'll have an empty graph which we'll use to store //up the set of triples to be removed g.Assert(new Triple(subj, pred, obj)); } } if (this._manager.UpdateSupported) { this._manager.UpdateGraph(graphUri, Enumerable.Empty<Triple>(), g.Triples); } else { this._manager.SaveGraph(g); } } } }
/// <summary> /// Processes a MOVE command /// </summary> /// <param name="cmd">Move Command</param> public void ProcessMoveCommand(MoveCommand cmd) { if (this._manager is IUpdateableGenericIOManager) { ((IUpdateableGenericIOManager)this._manager).Update(cmd.ToString()); } else { try { Graph source = new Graph(); this._manager.LoadGraph(source, cmd.SourceUri); source.BaseUri = cmd.SourceUri; //If the Manager supports delete ensure the Destination Graph is deleted if (this._manager.DeleteSupported) { try { this._manager.DeleteGraph(cmd.DestinationUri); } catch (Exception ex) { throw new SparqlUpdateException("Unable to process a MOVE command as unable to ensure that the Destination Graph was deleted prior to moving the data from the Source Graph", ex); } } //Load Destination Graph and ensure it is empty Graph dest = new Graph(); this._manager.LoadGraph(dest, cmd.DestinationUri); dest.BaseUri = cmd.DestinationUri; dest.Clear(); //Transfer the data and update both the Graphs //For the Source Graph which we must delete the contents of either use DeleteGraph() if supported or //just save an empty Graph in its place and hope that SaveGraph() is an overwrite operation dest.Merge(source); source.Clear(); this._manager.SaveGraph(dest); if (this._manager.DeleteSupported) { try { this._manager.DeleteGraph(cmd.SourceUri); } catch (Exception ex) { throw new SparqlUpdateException("Unable to process a MOVE command as unable to ensure that the Source Graph was deleted after the movement of data to the Destination Graph", ex); } } else { this._manager.SaveGraph(source); } } catch { if (!cmd.Silent) throw; } } }
/// <summary> /// Processes a DROP command /// </summary> /// <param name="cmd">Drop Command</param> public void ProcessDropCommand(DropCommand cmd) { if (this._manager is IUpdateableGenericIOManager) { ((IUpdateableGenericIOManager)this._manager).Update(cmd.ToString()); } else { try { Graph g; switch (cmd.Mode) { case ClearMode.Graph: case ClearMode.Default: g = new Graph(); g.BaseUri = cmd.TargetUri; this._manager.SaveGraph(g); break; case ClearMode.All: case ClearMode.Named: if (this._manager.ListGraphsSupported) { List<Uri> graphs = this._manager.ListGraphs().ToList(); foreach (Uri u in graphs) { g = new Graph(); g.BaseUri = u; this._manager.SaveGraph(g); } } else { throw new NotSupportedException("The Generic Update processor does not support this form of the DROP command"); } break; } } catch { if (!cmd.Silent) throw; } } }
/// <summary> /// Adds a statement to this Source /// </summary> /// <param name="statement">Statement</param> /// <returns></returns> public bool Add(Statement statement) { IGraph g; Uri graphUri; int hash; //Set the Graph URI based on the Statement Meta field if (statement.Meta != Statement.DefaultMeta && statement.Meta.Uri != null) { if (statement.Meta.Uri.Equals(GraphCollection.DefaultGraphUri)) { graphUri = null; hash = new Uri(GraphCollection.DefaultGraphUri).GetEnhancedHashCode(); } else { graphUri = new Uri(statement.Meta.Uri); hash = graphUri.GetEnhancedHashCode(); } } else { graphUri = null; hash = new Uri(GraphCollection.DefaultGraphUri).GetEnhancedHashCode(); } if (!this._store.HasGraph(graphUri)) { g = new Graph(); if (graphUri != null) g.BaseUri = graphUri; this._store.Add(g); } else { g = this._store.Graph(graphUri); } //Assert into the appropriate Graph g.Assert(SemWebConverter.FromSemWeb(statement, this.GetMapping(hash, g))); //We never ask the sink to stop streaming statements so we always return true return true; }
public void SparqlBgpEvaluation() { //Prepare the Store TripleStore store = new TripleStore(); Graph g = new Graph(); FileLoader.Load(g, "Turtle.ttl"); store.Add(g); SparqlQueryParser parser = new SparqlQueryParser(); SparqlQuery q = parser.ParseFromString(@"PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> SELECT * WHERE {?s ?p ?o . ?s rdfs:label ?label}"); Object testResult = store.ExecuteQuery(q); ISparqlAlgebra testAlgebra = q.ToAlgebra(); if (testResult is SparqlResultSet) { SparqlResultSet rset = (SparqlResultSet)testResult; Console.WriteLine(rset.Count + " Results"); foreach (SparqlResult r in rset) { Console.WriteLine(r.ToString()); } Console.WriteLine(); } //Create some Triple Patterns TriplePattern t1 = new TriplePattern(new VariablePattern("?s"), new VariablePattern("?p"), new VariablePattern("?o")); TriplePattern t2 = new TriplePattern(new VariablePattern("?s"), new NodeMatchPattern(g.CreateUriNode("rdfs:label")), new VariablePattern("?label")); TriplePattern t3 = new TriplePattern(new VariablePattern("?x"), new VariablePattern("?y"), new VariablePattern("?z")); TriplePattern t4 = new TriplePattern(new VariablePattern("?s"), new NodeMatchPattern(g.CreateUriNode(":name")), new VariablePattern("?name")); //Build some BGPs Bgp selectNothing = new Bgp(); Bgp selectAll = new Bgp(t1); Bgp selectLabelled = new Bgp(new List<ITriplePattern>() { t1, t2 }); Bgp selectAllDisjoint = new Bgp(new List<ITriplePattern>() { t1, t3 }); Bgp selectLabels = new Bgp(t2); Bgp selectNames = new Bgp(t4); //LeftJoin selectOptionalNamed = new LeftJoin(selectAll, new Optional(selectNames)); LeftJoin selectOptionalNamed = new LeftJoin(selectAll, selectNames); Union selectAllUnion = new Union(selectAll, selectAll); Union selectAllUnion2 = new Union(selectAllUnion, selectAll); Filter selectAllUriObjects = new Filter(selectAll, new UnaryExpressionFilter(new IsUriFunction(new VariableExpressionTerm("o")))); //Test out the BGPs //Console.WriteLine("{}"); //this.ShowMultiset(selectNothing.Evaluate(new SparqlEvaluationContext(null, store))); //Console.WriteLine("{?s ?p ?o}"); //this.ShowMultiset(selectAll.Evaluate(new SparqlEvaluationContext(null, store))); //Console.WriteLine("{?s ?p ?o . ?s rdfs:label ?label}"); //SparqlEvaluationContext context = new SparqlEvaluationContext(null, store); //this.ShowMultiset(selectLabelled.Evaluate(context)); //SparqlResultSet lvnResult = new SparqlResultSet(context); //Console.WriteLine("{?s ?p ?o . ?x ?y ?z}"); //this.ShowMultiset(selectAllDisjoint.Evaluate(new SparqlEvaluationContext(null, store))); //Console.WriteLine("{?s ?p ?o . OPTIONAL {?s :name ?name}}"); //this.ShowMultiset(selectOptionalNamed.Evaluate(new SparqlEvaluationContext(null, store))); Console.WriteLine("{{?s ?p ?o} UNION {?s ?p ?o}}"); this.ShowMultiset(selectAllUnion.Evaluate(new SparqlEvaluationContext(null, new InMemoryDataset(store)))); Console.WriteLine("{{?s ?p ?o} UNION {?s ?p ?o} UNION {?s ?p ?o}}"); this.ShowMultiset(selectAllUnion2.Evaluate(new SparqlEvaluationContext(null, new InMemoryDataset(store)))); Console.WriteLine("{?s ?p ?o FILTER (ISURI(?o))}"); this.ShowMultiset(selectAllUriObjects.Evaluate(new SparqlEvaluationContext(null, new InMemoryDataset(store)))); }
/// <summary> /// Processes an INSERT/DELETE command /// </summary> /// <param name="cmd">Insert/Delete Command</param> public void ProcessModifyCommand(ModifyCommand cmd) { if (this._manager is IUpdateableGenericIOManager) { ((IUpdateableGenericIOManager)this._manager).Update(cmd.ToString()); } else { if (this._manager is IQueryableGenericIOManager) { //First build and make the query to get a Result Set String queryText = "SELECT * WHERE " + cmd.WherePattern.ToString(); SparqlQueryParser parser = new SparqlQueryParser(); SparqlQuery query = parser.ParseFromString(queryText); if (cmd.GraphUri != null && !cmd.UsingUris.Any()) query.AddDefaultGraph(cmd.GraphUri); foreach (Uri u in cmd.UsingUris) { query.AddDefaultGraph(u); } foreach (Uri u in cmd.UsingNamedUris) { query.AddNamedGraph(u); } Object results = ((IQueryableGenericIOManager)this._manager).Query(query.ToString()); if (results is SparqlResultSet) { //Now need to transform the Result Set back to a Multiset Multiset mset = new Multiset((SparqlResultSet)results); //Generate the Triples for each Solution List<Triple> deletedTriples = new List<Triple>(); Dictionary<String, List<Triple>> deletedGraphTriples = new Dictionary<string, List<Triple>>(); foreach (Set s in mset.Sets) { List<Triple> tempDeletedTriples = new List<Triple>(); try { ConstructContext context = new ConstructContext(null, s, true); foreach (IConstructTriplePattern p in cmd.DeletePattern.TriplePatterns.OfType<IConstructTriplePattern>()) { try { tempDeletedTriples.Add(p.Construct(context)); } catch (RdfQueryException) { //If we get an error here then it means we could not construct a specific //triple so we continue anyway } } deletedTriples.AddRange(tempDeletedTriples); } catch (RdfQueryException) { //If we get an error here this means we couldn't construct for this solution so the //solution is ignored for this graph } //Triples from GRAPH clauses foreach (GraphPattern gp in cmd.DeletePattern.ChildGraphPatterns) { tempDeletedTriples.Clear(); try { String graphUri; switch (gp.GraphSpecifier.TokenType) { case Token.URI: graphUri = gp.GraphSpecifier.Value; break; case Token.VARIABLE: if (s.ContainsVariable(gp.GraphSpecifier.Value)) { INode temp = s[gp.GraphSpecifier.Value.Substring(1)]; if (temp == null) { //If the Variable is not bound then skip continue; } else if (temp.NodeType == NodeType.Uri) { graphUri = temp.ToSafeString(); } else { //If the Variable is not bound to a URI then skip continue; } } else { //If the Variable is not bound for this solution then skip continue; } break; default: //Any other Graph Specifier we have to ignore this solution continue; } if (!deletedGraphTriples.ContainsKey(graphUri)) deletedGraphTriples.Add(graphUri, new List<Triple>()); ConstructContext context = new ConstructContext(null, s, true); foreach (IConstructTriplePattern p in gp.TriplePatterns.OfType<IConstructTriplePattern>()) { try { tempDeletedTriples.Add(p.Construct(context)); } catch (RdfQueryException) { //If we throw an error this means we couldn't construct a specific //triple so we continue anyway } } deletedGraphTriples[graphUri].AddRange(tempDeletedTriples); } catch (RdfQueryException) { //If we get an error here this means we couldn't construct for this solution so the //solution is ignored for this graph } } } //Generate the Triples for each Solution List<Triple> insertedTriples = new List<Triple>(); Dictionary<String, List<Triple>> insertedGraphTriples = new Dictionary<string, List<Triple>>(); foreach (Set s in mset.Sets) { List<Triple> tempInsertedTriples = new List<Triple>(); try { ConstructContext context = new ConstructContext(null, s, true); foreach (IConstructTriplePattern p in cmd.InsertPattern.TriplePatterns.OfType<IConstructTriplePattern>()) { try { tempInsertedTriples.Add(p.Construct(context)); } catch (RdfQueryException) { //If we get an error here then it means we couldn't construct a specific //triple so we continue anyway } } insertedTriples.AddRange(tempInsertedTriples); } catch (RdfQueryException) { //If we get an error here this means we couldn't construct for this solution so the //solution is ignored for this graph } //Triples from GRAPH clauses foreach (GraphPattern gp in cmd.InsertPattern.ChildGraphPatterns) { tempInsertedTriples.Clear(); try { String graphUri; switch (gp.GraphSpecifier.TokenType) { case Token.URI: graphUri = gp.GraphSpecifier.Value; break; case Token.VARIABLE: if (s.ContainsVariable(gp.GraphSpecifier.Value)) { INode temp = s[gp.GraphSpecifier.Value.Substring(1)]; if (temp == null) { //If the Variable is not bound then skip continue; } else if (temp.NodeType == NodeType.Uri) { graphUri = temp.ToSafeString(); } else { //If the Variable is not bound to a URI then skip continue; } } else { //If the Variable is not bound for this solution then skip continue; } break; default: //Any other Graph Specifier we have to ignore this solution continue; } if (!insertedGraphTriples.ContainsKey(graphUri)) insertedGraphTriples.Add(graphUri, new List<Triple>()); ConstructContext context = new ConstructContext(null, s, true); foreach (IConstructTriplePattern p in gp.TriplePatterns.OfType<IConstructTriplePattern>()) { try { tempInsertedTriples.Add(p.Construct(context)); } catch (RdfQueryException) { //If we get an error here it means we couldn't construct a specific //triple so we continue anyway } } insertedGraphTriples[graphUri].AddRange(tempInsertedTriples); } catch (RdfQueryException) { //If we get an error here this means we couldn't construct for this solution so the //solution is ignored for this graph } } } //Now decide how to apply the update if (this._manager.UpdateSupported) { this._manager.UpdateGraph(cmd.GraphUri, insertedTriples, deletedTriples); //We do these two operations sequentially even if in some cases they could be combined to ensure that the underlying //Manager doesn't do any optimisations which would have the result of our updates not being properly applied //e.g. ignoring Triples which are both asserted and retracted in one update foreach (KeyValuePair<String, List<Triple>> graphDeletion in deletedGraphTriples) { this._manager.UpdateGraph(graphDeletion.Key, Enumerable.Empty<Triple>(), graphDeletion.Value); } foreach (KeyValuePair<String, List<Triple>> graphInsertion in insertedGraphTriples) { this._manager.UpdateGraph(graphInsertion.Key, graphInsertion.Value, Enumerable.Empty<Triple>()); } } else { Graph g = new Graph(); this._manager.LoadGraph(g, cmd.GraphUri); g.Retract(deletedTriples); this._manager.SaveGraph(g); foreach (String graphUri in deletedGraphTriples.Keys.Concat(insertedGraphTriples.Keys).Distinct()) { g = new Graph(); this._manager.LoadGraph(g, graphUri); if (deletedGraphTriples.ContainsKey(graphUri)) g.Retract(deletedGraphTriples[graphUri]); if (insertedGraphTriples.ContainsKey(graphUri)) g.Assert(insertedGraphTriples[graphUri]); this._manager.SaveGraph(g); } } } else { throw new SparqlUpdateException("Cannot evaluate an INSERT/DELETE Command as the underlying Store failed to answer the query for the WHERE portion of the command as expected"); } } else { throw new NotSupportedException("INSERT/DELETE commands are not supported by this Update Processor as the manager for the underlying Store does not provide Query capabilities which are necessary to process this command"); } } }
/// <summary> /// Gets the Description Graph based on the Query Results from the given Evaluation Context /// </summary> /// <param name="context">SPARQL Evaluation Context</param> /// <returns></returns> public IGraph Describe(SparqlEvaluationContext context) { Graph g = new Graph(); this.Describe(new GraphHandler(g), context); return g; }
/// <summary> /// Processes an ADD command /// </summary> /// <param name="cmd">Add Command</param> public void ProcessAddCommand(AddCommand cmd) { if (this._manager is IUpdateableGenericIOManager) { ((IUpdateableGenericIOManager)this._manager).Update(cmd.ToString()); } else { try { Graph source = new Graph(); this._manager.LoadGraph(source, cmd.SourceUri); source.BaseUri = cmd.SourceUri; //Load Destination Graph Graph dest = new Graph(); this._manager.LoadGraph(dest, cmd.DestinationUri); dest.BaseUri = cmd.DestinationUri; //Transfer the data and update the Destination Graph dest.Merge(source); this._manager.SaveGraph(dest); } catch { if (!cmd.Silent) throw; } } }
/// <summary> /// Processes a LOAD command /// </summary> /// <param name="cmd">Load Command</param> public void ProcessLoadCommand(LoadCommand cmd) { if (this._manager is IUpdateableGenericIOManager) { ((IUpdateableGenericIOManager)this._manager).Update(cmd.ToString()); } else { try { Graph g = new Graph(); if (!this._manager.UpdateSupported) this._manager.LoadGraph(g, cmd.TargetUri); UriLoader.Load(g, cmd.SourceUri); g.BaseUri = cmd.TargetUri; if (this._manager.UpdateSupported) { this._manager.UpdateGraph(cmd.TargetUri, g.Triples, Enumerable.Empty<Triple>()); } else { this._manager.SaveGraph(g); } } catch { if (!cmd.Silent) throw; } } }
/// <summary> /// Processes an INSERT DATA command /// </summary> /// <param name="cmd">Insert Data Command</param> public void ProcessInsertDataCommand(InsertDataCommand cmd) { if (this._manager is IUpdateableGenericIOManager) { ((IUpdateableGenericIOManager)this._manager).Update(cmd.ToString()); } else { //Split the Pattern into the set of Graph Patterns List<GraphPattern> patterns = new List<GraphPattern>(); if (cmd.DataPattern.IsGraph) { patterns.Add(cmd.DataPattern); } else if (cmd.DataPattern.TriplePatterns.Count > 0 || cmd.DataPattern.HasChildGraphPatterns) { if (cmd.DataPattern.TriplePatterns.Count > 0) { patterns.Add(new GraphPattern()); cmd.DataPattern.TriplePatterns.ForEach(tp => patterns[0].AddTriplePattern(tp)); } cmd.DataPattern.ChildGraphPatterns.ForEach(gp => patterns.Add(gp)); } else { //If no Triple Patterns and No Child Graph Patterns nothing to do return; } foreach (GraphPattern pattern in patterns) { if (!this.IsValidDataPattern(pattern, false)) throw new SparqlUpdateException("Cannot evaluate an INSERT DATA command where any of the Triple Patterns are not concrete triples - variables are not permitted"); Uri graphUri = null; if (pattern.IsGraph) { switch (pattern.GraphSpecifier.TokenType) { case Token.QNAME: throw new NotImplementedException("Graph Specifiers as QNames for INSERT DATA Commands are not supported - please specify an absolute URI instead"); case Token.URI: graphUri = new Uri(pattern.GraphSpecifier.Value); break; default: throw new SparqlUpdateException("Cannot evaluate an INSERT DATA Command as the Graph Specifier is not a QName/URI"); } } Graph g = new Graph(); if (!this._manager.UpdateSupported) this._manager.LoadGraph(g, graphUri); //Insert the actual Triples INode subj, pred, obj; ConstructContext context = new ConstructContext(g, null, true); foreach (IConstructTriplePattern p in pattern.TriplePatterns.OfType<IConstructTriplePattern>()) { subj = p.Subject.Construct(context); pred = p.Predicate.Construct(context); obj = p.Object.Construct(context); g.Assert(new Triple(subj, pred, obj)); } if (this._manager.UpdateSupported) { this._manager.UpdateGraph(graphUri, g.Triples, Enumerable.Empty<Triple>()); } else { this._manager.SaveGraph(g); } } } }
/// <summary> /// Processes a SPARQL Query asynchronously invoking the relevant callback when the query completes /// </summary> /// <param name="query">SPARQL QUery</param> /// <param name="rdfCallback">Callback for queries that return a Graph</param> /// <param name="resultsCallback">Callback for queries that return a Result Set</param> /// <param name="state">State to pass to the callback</param> public void ProcessQuery(SparqlQuery query, GraphCallback rdfCallback, SparqlResultsCallback resultsCallback, Object state) { Graph g = new Graph(); SparqlResultSet rset = new SparqlResultSet(); ProcessQueryAsync d = new ProcessQueryAsync(this.ProcessQuery); d.BeginInvoke(new GraphHandler(g), new ResultSetHandler(rset), query, r => { d.EndInvoke(r); if (rset.ResultsType != SparqlResultsType.Unknown) { resultsCallback(rset, state); } else { rdfCallback(g, state); } }, state); }
public void SparqlStreamingBgpSelectEvaluation() { //Get the Data we want to query TripleStore store = new TripleStore(); Graph g = new Graph(); FileLoader.Load(g, "InferenceTest.ttl"); store.Add(g); //g = new Graph(); //FileLoader.Load(g, "noise.ttl"); //store.Add(g); Console.WriteLine(store.Triples.Count() + " Triples in Store"); //Create the Triple Pattern we want to query with IUriNode fordFiesta = g.CreateUriNode(new Uri("http://example.org/vehicles/FordFiesta")); IUriNode rdfType = g.CreateUriNode(new Uri(RdfSpecsHelper.RdfType)); IUriNode rdfsLabel = g.CreateUriNode(new Uri(NamespaceMapper.RDFS + "label")); IUriNode speed = g.CreateUriNode(new Uri("http://example.org/vehicles/Speed")); IUriNode carClass = g.CreateUriNode(new Uri("http://example.org/vehicles/Car")); TriplePattern allTriples = new TriplePattern(new VariablePattern("?s"), new VariablePattern("?p"), new VariablePattern("?o")); TriplePattern allTriples2 = new TriplePattern(new VariablePattern("?x"), new VariablePattern("?y"), new VariablePattern("?z")); TriplePattern tp1 = new TriplePattern(new VariablePattern("?s"), new NodeMatchPattern(rdfType), new NodeMatchPattern(carClass)); TriplePattern tp2 = new TriplePattern(new VariablePattern("?s"), new NodeMatchPattern(speed), new VariablePattern("?speed")); TriplePattern tp3 = new TriplePattern(new VariablePattern("?s"), new NodeMatchPattern(rdfsLabel), new VariablePattern("?label")); TriplePattern novars = new TriplePattern(new NodeMatchPattern(fordFiesta), new NodeMatchPattern(rdfType), new NodeMatchPattern(carClass)); TriplePattern novars2 = new TriplePattern(new NodeMatchPattern(fordFiesta), new NodeMatchPattern(rdfsLabel), new NodeMatchPattern(carClass)); FilterPattern blankSubject = new FilterPattern(new UnaryExpressionFilter(new IsBlankFunction(new VariableExpressionTerm("?s")))); List<List<ITriplePattern>> tests = new List<List<ITriplePattern>>() { new List<ITriplePattern>() { }, new List<ITriplePattern>() { allTriples }, new List<ITriplePattern>() { allTriples, allTriples2 }, new List<ITriplePattern>() { tp1 }, new List<ITriplePattern>() { tp1, tp2 }, new List<ITriplePattern>() { tp1, tp3 }, new List<ITriplePattern>() { novars }, new List<ITriplePattern>() { novars, tp1 }, new List<ITriplePattern>() { novars, tp1, tp2 }, new List<ITriplePattern>() { novars2 }, new List<ITriplePattern>() { tp1, blankSubject } }; foreach (List<ITriplePattern> tps in tests) { Console.WriteLine(tps.Count + " Triple Patterns in the Query"); foreach (ITriplePattern tp in tps) { Console.WriteLine(tp.ToString()); } Console.WriteLine(); ISparqlAlgebra select = new Bgp(tps); ISparqlAlgebra selectOptimised = new LazyBgp(tps, 10); //Evaluate with timings Stopwatch timer = new Stopwatch(); TimeSpan unopt, opt; timer.Start(); BaseMultiset results1 = select.Evaluate(new SparqlEvaluationContext(null, new InMemoryDataset(store))); timer.Stop(); unopt = timer.Elapsed; timer.Reset(); timer.Start(); BaseMultiset results2 = selectOptimised.Evaluate(new SparqlEvaluationContext(null, new InMemoryDataset(store))); timer.Stop(); opt = timer.Elapsed; Console.WriteLine("SELECT = " + results1.GetType().ToString() + " (" + results1.Count + " Results) in " + unopt.ToString()); Console.WriteLine("SELECT Optimised = " + results2.GetType().ToString() + " (" + results2.Count + " Results) in " + opt.ToString()); Console.WriteLine(); Console.WriteLine("Optimised Results"); foreach (Set s in results2.Sets) { Console.WriteLine(s.ToString()); } Assert.IsTrue(results1.Count >= results2.Count, "Optimised Select should have produced as many/fewer results than Unoptimised Select"); Console.WriteLine(); } }
/// <summary> /// Returns the Graph which is the Result of the Describe Query by computing the Labelled Description for all Results /// </summary> /// <param name="context">SPARQL Evaluation Context</param> /// <returns></returns> public override IGraph Describe(SparqlEvaluationContext context) { //Get a new empty Graph and import the Base Uri and Namespace Map of the Query Graph g = new Graph(); g.BaseUri = context.Query.BaseUri; g.NamespaceMap.Import(context.Query.NamespaceMap); //Build a list of INodes to describe List<INode> nodes = new List<INode>(); foreach (IToken t in context.Query.DescribeVariables) { switch (t.TokenType) { case Token.QNAME: case Token.URI: //Resolve Uri/QName nodes.Add(new UriNode(g, new Uri(Tools.ResolveUriOrQName(t, g.NamespaceMap, g.BaseUri)))); break; case Token.VARIABLE: //Get Variable Values String var = t.Value.Substring(1); if (context.OutputMultiset.ContainsVariable(var)) { foreach (Set s in context.OutputMultiset.Sets) { INode temp = s[var]; if (temp != null) nodes.Add(temp); } } break; default: throw new RdfQueryException("Unexpected Token '" + t.GetType().ToString() + "' in DESCRIBE Variables list"); } } //Rewrite Blank Node IDs for DESCRIBE Results Dictionary<String, INode> bnodeMapping = new Dictionary<string, INode>(); //Get Triples for this Subject Queue<INode> bnodes = new Queue<INode>(); HashSet<INode> expandedBNodes = new HashSet<INode>(); INode rdfsLabel = g.CreateUriNode(new Uri(NamespaceMapper.RDFS + "label")); foreach (INode n in nodes) { //Get Triples where the Node is the Subject foreach (Triple t in context.Data.GetTriplesWithSubject(n)) { if (t.Object.NodeType == NodeType.Blank) { if (!expandedBNodes.Contains(t.Object)) bnodes.Enqueue(t.Object); } g.Assert(this.RewriteDescribeBNodes(t, bnodeMapping, g)); } //Compute the Blank Node Closure for this Subject while (bnodes.Count > 0) { INode bsubj = bnodes.Dequeue(); if (expandedBNodes.Contains(bsubj)) continue; expandedBNodes.Add(bsubj); foreach (Triple t2 in context.Data.GetTriplesWithSubjectPredicate(bsubj, rdfsLabel)) { g.Assert(this.RewriteDescribeBNodes(t2, bnodeMapping, g)); } } } //Return the Graph g.BaseUri = null; return g; }
private void PrintGraphAnalysis(Algebra.Graph graph, SparqlEvaluationContext context) { if (!HasFlag(ExplanationLevel.AnalyseNamedGraphs)) { return; } switch (graph.GraphSpecifier.TokenType) { case Token.QNAME: case Token.URI: // Only a single active graph Uri activeGraphUri = UriFactory.Create(Tools.ResolveUriOrQName(graph.GraphSpecifier, context.Query.NamespaceMap, context.Query.BaseUri)); PrintExplanations("Graph clause accesses single named graph " + activeGraphUri.AbsoluteUri); break; case Token.VARIABLE: // Potentially many active graphs List <String> activeGraphs = new List <string>(); String gvar = graph.GraphSpecifier.Value.Substring(1); // Watch out for the case in which the Graph Variable is not bound for all Sets in which case // we still need to operate over all Graphs if (context.InputMultiset.ContainsVariable(gvar) && context.InputMultiset.Sets.All(s => s[gvar] != null)) { // If there are already values bound to the Graph variable for all Input Solutions then we limit the Query to those Graphs List <Uri> graphUris = new List <Uri>(); foreach (ISet s in context.InputMultiset.Sets) { INode temp = s[gvar]; if (temp == null) { continue; } if (temp.NodeType != NodeType.Uri) { continue; } activeGraphs.Add(temp.ToString()); graphUris.Add(((IUriNode)temp).Uri); } } else { // Worth explaining that the graph variable is partially bound if (context.InputMultiset.ContainsVariable(gvar)) { PrintExplanations("Graph clause uses variable ?" + gvar + " to specify named graphs, this variable is only partially bound at this point in the query so can't be use to restrict list of named graphs to access"); } // Nothing yet bound to the Graph Variable so the Query is over all the named Graphs if (context.Query != null && context.Query.NamedGraphs.Any()) { // Query specifies one/more named Graphs PrintExplanations("Graph clause uses variable ?" + gvar + " which is restricted to graphs specified by the queries FROM NAMED clause(s)"); activeGraphs.AddRange(context.Query.NamedGraphs.Select(u => u.AbsoluteUri)); } else if (context.Query != null && context.Query.DefaultGraphs.Any() && !context.Query.NamedGraphs.Any()) { // Gives null since the query dataset does not include any named graphs PrintExplanations("Graph clause uses variable ?" + gvar + " which will match no graphs because the queries dataset description does not include any named graphs i.e. there where FROM clauses but no FROM NAMED clauses"); return; } else { // Query is over entire dataset/default Graph since no named Graphs are explicitly specified PrintExplanations("Graph clause uses variable ?" + gvar + " which accesses all named graphs provided by the dataset"); activeGraphs.AddRange(context.Data.GraphUris.Select(u => u.ToSafeString())); } } // Remove all duplicates from Active Graphs to avoid duplicate results activeGraphs = activeGraphs.Distinct().ToList(); activeGraphs.RemoveAll(x => x == null); PrintExplanations("Graph clause will access the following " + activeGraphs.Count + " graphs:"); foreach (String uri in activeGraphs) { PrintExplanations(uri); } break; default: throw new RdfQueryException("Cannot use a '" + graph.GraphSpecifier.GetType() + "' Token to specify the Graph for a GRAPH clause"); } }
/// <summary> /// Processes an INSERT DATA command /// </summary> /// <param name="cmd">Insert Data Command</param> public void ProcessInsertDataCommand(InsertDataCommand cmd) { if (this._manager is IUpdateableGenericIOManager) { ((IUpdateableGenericIOManager)this._manager).Update(cmd.ToString()); } else { //Check IO Behaviour //For a insert we either need the ability to Update Delete Triples or to Overwrite Graphs //Firstly check behaviour persuant to default graph if applicable if (cmd.DataPattern.TriplePatterns.OfType<IConstructTriplePattern>().Any()) { //Must support notion of default graph if ((this._manager.IOBehaviour & IOBehaviour.HasDefaultGraph) == 0) throw new SparqlUpdateException("The underlying store does not support the notion of an explicit unnamed Default Graph required to process this command"); //Must allow either OverwriteDefault or CanUpdateAddTriples if ((this._manager.IOBehaviour & IOBehaviour.CanUpdateAddTriples) == 0 && (this._manager.IOBehaviour & IOBehaviour.OverwriteDefault) == 0) throw new SparqlUpdateException("The underlying store does not support the required IO Behaviour to implement this command"); } //Then check behaviour persuant to named graphs if applicable if (cmd.DataPattern.HasChildGraphPatterns) { //Must support named graphs if ((this._manager.IOBehaviour & IOBehaviour.HasNamedGraphs) == 0) throw new SparqlUpdateException("The underlying store does not support the notion of named graphs required to process this command"); //Must allow either CanUpdateAddTriples or OverwriteNamed if ((this._manager.IOBehaviour & IOBehaviour.CanUpdateAddTriples) == 0 && (this._manager.IOBehaviour & IOBehaviour.OverwriteNamed) == 0) throw new SparqlUpdateException("The underlying store does not support the required IO Behaviour to implement this command"); } //Split the Pattern into the set of Graph Patterns List<GraphPattern> patterns = new List<GraphPattern>(); if (cmd.DataPattern.IsGraph) { patterns.Add(cmd.DataPattern); } else if (cmd.DataPattern.TriplePatterns.Count > 0 || cmd.DataPattern.HasChildGraphPatterns) { if (cmd.DataPattern.TriplePatterns.Count > 0) { patterns.Add(new GraphPattern()); cmd.DataPattern.TriplePatterns.ForEach(tp => patterns[0].AddTriplePattern(tp)); } cmd.DataPattern.ChildGraphPatterns.ForEach(gp => patterns.Add(gp)); } else { //If no Triple Patterns and No Child Graph Patterns nothing to do return; } foreach (GraphPattern pattern in patterns) { if (!this.IsValidDataPattern(pattern, false)) throw new SparqlUpdateException("Cannot evaluate an INSERT DATA command where any of the Triple Patterns are not concrete triples - variables are not permitted"); Uri graphUri = null; if (pattern.IsGraph) { switch (pattern.GraphSpecifier.TokenType) { case Token.QNAME: throw new NotSupportedException("Graph Specifiers as QNames for INSERT DATA Commands are not supported - please specify an absolute URI instead"); case Token.URI: graphUri = UriFactory.Create(pattern.GraphSpecifier.Value); break; default: throw new SparqlUpdateException("Cannot evaluate an INSERT DATA Command as the Graph Specifier is not a QName/URI"); } } Graph g = new Graph(); if (!this._manager.UpdateSupported) this._manager.LoadGraph(g, graphUri); //Insert the actual Triples INode subj, pred, obj; ConstructContext context = new ConstructContext(g, null, true); foreach (IConstructTriplePattern p in pattern.TriplePatterns.OfType<IConstructTriplePattern>()) { subj = p.Subject.Construct(context); pred = p.Predicate.Construct(context); obj = p.Object.Construct(context); g.Assert(new Triple(subj, pred, obj)); } if (this._manager.UpdateSupported) { this._manager.UpdateGraph(graphUri, g.Triples, Enumerable.Empty<Triple>()); } else { this._manager.SaveGraph(g); } } } }
/// <summary> /// Processes a CREATE command /// </summary> /// <param name="cmd">Create Command</param> /// <remarks> /// <para> /// Implemented by adding an empty Graph to the Store /// </para> /// <para> /// <strong>Warning:</strong> As the <see cref="IGenericIOManager">IGenericIOManager</see> interface does not allow checking whether a Graph exists processing CREATE commands can result in overwriting existing Graphs /// </para> /// </remarks> public void ProcessCreateCommand(CreateCommand cmd) { if (this._manager is IUpdateableGenericIOManager) { ((IUpdateableGenericIOManager)this._manager).Update(cmd.ToString()); } else { Graph g = new Graph(); g.BaseUri = cmd.TargetUri; try { this._manager.SaveGraph(g); } catch { if (!cmd.Silent) throw; } } }
/// <summary> /// Helper method which transforms a set of Statement Templates to an Algebra BGP /// </summary> /// <param name="statements">Statement Templates</param> /// <returns></returns> private ISparqlAlgebra ToAlgebra(Statement[] statements) { Graph g = new Graph(); List<ITriplePattern> patterns = new List<ITriplePattern>(); Dictionary<String, PatternItem> mapping = new Dictionary<string, PatternItem>(); foreach (Statement stmt in statements) { //Build a Triple Pattern for each part of the Statement PatternItem s, p, o; s = this.FromSemWeb(stmt.Subject, g, mapping); p = this.FromSemWeb(stmt.Predicate, g, mapping); o = this.FromSemWeb(stmt.Object, g, mapping); patterns.Add(new TriplePattern(s, p, o)); //If any of the parts were a Blank Node apply an IsBlank() FILTER if (stmt.Subject is BNode && !(stmt.Subject is Variable)) patterns.Add(new FilterPattern(new UnaryExpressionFilter(new IsBlankFunction(new VariableExpressionTerm(s.VariableName))))); if (stmt.Predicate is BNode && !(stmt.Predicate is Variable)) patterns.Add(new FilterPattern(new UnaryExpressionFilter(new IsBlankFunction(new VariableExpressionTerm(p.VariableName))))); if (stmt.Object is BNode && !(stmt.Object is Variable)) patterns.Add(new FilterPattern(new UnaryExpressionFilter(new IsBlankFunction(new VariableExpressionTerm(o.VariableName))))); } return new Bgp(patterns); }
/// <summary> /// Processes an ADD command /// </summary> /// <param name="cmd">Add Command</param> public void ProcessAddCommand(AddCommand cmd) { if (this._manager is IUpdateableGenericIOManager) { ((IUpdateableGenericIOManager)this._manager).Update(cmd.ToString()); } else { try { //If Source and Destination are equal this is a no-op if (EqualityHelper.AreUrisEqual(cmd.SourceUri, cmd.DestinationUri)) return; //Firstly check that appropriate IO Behaviour is provided if (cmd.SourceUri == null || cmd.DestinationUri == null) { if ((this._manager.IOBehaviour & IOBehaviour.HasDefaultGraph) == 0) throw new SparqlUpdateException("The underlying store does not provide support for an explicit unnamed Default Graph required to process this command"); } IOBehaviour desired = cmd.DestinationUri == null ? IOBehaviour.OverwriteDefault : IOBehaviour.OverwriteNamed; if ((this._manager.IOBehaviour & desired) == 0) throw new SparqlUpdateException("The underlying store does not provide the required IO Behaviour to implement this command"); //Load Source Graph Graph source = new Graph(); this._manager.LoadGraph(source, cmd.SourceUri); source.BaseUri = cmd.SourceUri; //Load Destination Graph Graph dest = new Graph(); this._manager.LoadGraph(dest, cmd.DestinationUri); dest.BaseUri = cmd.DestinationUri; //Transfer the data and update the Destination Graph dest.Merge(source); this._manager.SaveGraph(dest); } catch { if (!cmd.Silent) throw; } } }
public void SparqlPropertyPathParser() { //Load our test data TripleStore store = new TripleStore(); Graph g = new Graph(); FileLoader.Load(g, "InferenceTest.ttl"); store.Add(g); List<String> testQueries = new List<string>(); String rdfsPrefix = "PREFIX rdfs: <" + NamespaceMapper.RDFS + ">\n"; //Cardinality Paths testQueries.Add(rdfsPrefix + "SELECT * WHERE {?subclass rdfs:subClassOf* <http://example.org/vehicles/Vehicle>}"); testQueries.Add(rdfsPrefix + "SELECT * WHERE {?subclass rdfs:subClassOf+ <http://example.org/vehicles/Vehicle>}"); testQueries.Add(rdfsPrefix + "SELECT * WHERE {?subclass rdfs:subClassOf? <http://example.org/vehicles/Vehicle>}"); testQueries.Add(rdfsPrefix + "SELECT * WHERE {?subclass rdfs:subClassOf{2,4} <http://example.org/vehicles/Vehicle>}"); testQueries.Add(rdfsPrefix + "SELECT * WHERE {?subclass rdfs:subClassOf{2,} <http://example.org/vehicles/Vehicle>}"); testQueries.Add(rdfsPrefix + "SELECT * WHERE {?subclass rdfs:subClassOf{,4} <http://example.org/vehicles/Vehicle>}"); testQueries.Add(rdfsPrefix + "SELECT * WHERE {?subclass rdfs:subClassOf{2} <http://example.org/vehicles/Vehicle>}"); //Simple Inverse Paths testQueries.Add(rdfsPrefix + "SELECT * WHERE {?type ^a ?entity}"); //Sequence Paths testQueries.Add(rdfsPrefix + "SELECT * WHERE {?subclass rdfs:subClassOf / rdfs:subClassOf <http://example.org/vehicles/Vehicle>}"); testQueries.Add(rdfsPrefix + "SELECT * WHERE {?subclass rdfs:subClassOf{2} / rdfs:subClassOf <http://example.org/vehicles/Vehicle>}"); testQueries.Add(rdfsPrefix + "SELECT * WHERE {?subclass rdfs:subClassOf / rdfs:subClassOf{2} <http://example.org/vehicles/Vehicle>}"); testQueries.Add(rdfsPrefix + "SELECT * WHERE {?subclass a / rdfs:subClassOf <http://example.org/vehicles/Plane>}"); testQueries.Add(rdfsPrefix + "SELECT * WHERE {?vehicle a ^ rdfs:subClassOf <http://example.org/vehicles/Plane>}"); testQueries.Add(rdfsPrefix + "SELECT * WHERE {?subclass a / ^ rdfs:subClassOf <http://example.org/vehicles/Vehicle>}"); testQueries.Add(rdfsPrefix + "SELECT * WHERE {?entity a ^ a ?type}"); testQueries.Add(rdfsPrefix + "SELECT * WHERE {?entity a ^ a / rdfs:subClassOf <http://example.org/vehicles/GroundVehicle>}"); //Alternative Paths testQueries.Add(rdfsPrefix + "SELECT * WHERE {?subclass rdfs:subClassOf | a <http://example.org/vehicles/Vehicle>}"); testQueries.Add(rdfsPrefix + "SELECT * WHERE {?subclass (rdfs:subClassOf | a) | rdfs:someProperty <http://example.org/vehicles/Vehicle>}"); testQueries.Add(rdfsPrefix + "SELECT * WHERE {?subclass rdfs:subClassOf | a | rdfs:someProperty <http://example.org/vehicles/Vehicle>}"); SparqlQueryParser parser = new SparqlQueryParser(); foreach (String query in testQueries) { //Parse the Query and output to console SparqlQuery q = parser.ParseFromString(query); Console.WriteLine(q.ToString()); //Now we'll try and evaluate it (if this is possible) try { Object results = store.ExecuteQuery(q); Console.WriteLine("Evaluated OK"); TestTools.ShowResults(results); Console.WriteLine(); } catch (RdfQueryException queryEx) { Console.WriteLine("Unable to evaluate:"); Console.WriteLine(queryEx.Message); Console.WriteLine(queryEx.StackTrace); } } }
/// <summary> /// Processes a LOAD command /// </summary> /// <param name="cmd">Load Command</param> public void ProcessLoadCommand(LoadCommand cmd) { if (this._manager is IUpdateableGenericIOManager) { ((IUpdateableGenericIOManager)this._manager).Update(cmd.ToString()); } else { try { //Check IO Behaviour //For a load which is essentially an insert we either need the ability to Update Add Triples or to Overwrite Graphs if (cmd.TargetUri == null) { //Must support notion of default graph if ((this._manager.IOBehaviour & IOBehaviour.HasDefaultGraph) == 0) throw new SparqlUpdateException("The underlying store does not support the notion of an explicit unnamed Default Graph required to process this command"); //Must allow either OverwriteDefault or CanUpdateDeleteTriples if ((this._manager.IOBehaviour & IOBehaviour.CanUpdateAddTriples) == 0 && (this._manager.IOBehaviour & IOBehaviour.OverwriteDefault) == 0) throw new SparqlUpdateException("The underlying store does not support the required IO Behaviour to implement this command"); } else { //Must support named graphs if ((this._manager.IOBehaviour & IOBehaviour.HasNamedGraphs) == 0) throw new SparqlUpdateException("The underlying store does not support the notion of named graphs required to process this command"); //Must allow either CanUpdateDeleteTriples or OverwriteNamed if ((this._manager.IOBehaviour & IOBehaviour.CanUpdateAddTriples) == 0 && (this._manager.IOBehaviour & IOBehaviour.OverwriteNamed) == 0) throw new SparqlUpdateException("The underlying store does not support the required IO Behaviour to implement this command"); } #if !NO_SYNC_HTTP Graph g = new Graph(); if (!this._manager.UpdateSupported) this._manager.LoadGraph(g, cmd.TargetUri); UriLoader.Load(g, cmd.SourceUri); g.BaseUri = cmd.TargetUri; if (this._manager.UpdateSupported) { this._manager.UpdateGraph(cmd.TargetUri, g.Triples, Enumerable.Empty<Triple>()); } else { this._manager.SaveGraph(g); } #else throw new SparqlUpdateException("Executing the LOAD command requires synchronous HTTP requests which are not supported on your platform currently"); #endif } catch { if (!cmd.Silent) throw; } } }
public void SparqlMultisetLeftJoin() { //Create a load of Nodes to use in the tests Graph g = new Graph(); g.NamespaceMap.AddNamespace(String.Empty, new Uri("http://example.org")); IUriNode s1 = g.CreateUriNode(":s1"); IUriNode s2 = g.CreateUriNode(":s2"); IUriNode p1 = g.CreateUriNode(":p1"); IUriNode p2 = g.CreateUriNode(":p2"); IUriNode rdfsLabel = g.CreateUriNode("rdfs:label"); ILiteralNode o1 = g.CreateLiteralNode("Some Text"); ILiteralNode o2 = g.CreateLiteralNode("1", new Uri(XmlSpecsHelper.XmlSchemaDataTypeInteger)); //Create an ID and Null Multiset IdentityMultiset id = new IdentityMultiset(); NullMultiset nullset = new NullMultiset(); //Create and Populate a Multiset Multiset m = new Multiset(); Set s = new Set(); s.Add("s", s1); s.Add("p", p1); s.Add("o", o1); m.Add(s); s = new Set(); s.Add("s", s2); s.Add("p", p2); s.Add("o", o2); m.Add(s); //Create and Populate another Multiset Multiset n = new Multiset(); s = new Set(); s.Add("s", s1); s.Add("label", o1); n.Add(s); //Create and Populate another Multiset Multiset d = new Multiset(); s = new Set(); s.Add("s1", s1); s.Add("p1", p1); s.Add("o1", o1); d.Add(s); s = new Set(); s.Add("s1", s2); s.Add("p1", p2); s.Add("o1", o2); d.Add(s); //Show the Sets Console.WriteLine("LHS"); foreach (Set set in m.Sets) { Console.WriteLine(set.ToString()); } Console.WriteLine(); Console.WriteLine("RHS"); foreach (Set set in n.Sets) { Console.WriteLine(set.ToString()); } Console.WriteLine(); Console.WriteLine("D"); foreach (Set set in d.Sets) { Console.WriteLine(set.ToString()); } Console.WriteLine(); //Try a Join to Identity Console.WriteLine("Join ID-LHS"); BaseMultiset join = id.Join(m); foreach (Set set in join.Sets) { Console.WriteLine(set.ToString()); } Console.WriteLine(); //Try a Join to Identity Console.WriteLine("Join LHS-ID"); join = m.Join(id); foreach (Set set in join.Sets) { Console.WriteLine(set.ToString()); } Console.WriteLine(); //Try a Join to Null Console.WriteLine("Join NULL-LHS"); join = nullset.Join(m); foreach (Set set in join.Sets) { Console.WriteLine(set.ToString()); } Console.WriteLine(); //Try a Join to Null Console.WriteLine("Join LHS-NULL"); join = m.Join(nullset); foreach (Set set in join.Sets) { Console.WriteLine(set.ToString()); } Console.WriteLine(); //Try a LeftJoin Console.WriteLine("LeftJoin NULL-LHS"); BaseMultiset leftjoin = nullset.LeftJoin(m, new BooleanExpressionTerm(true)); foreach (Set set in leftjoin.Sets) { Console.WriteLine(set.ToString()); } Console.WriteLine(); //Try a LeftJoin Console.WriteLine("LeftJoin LHS-NULL"); leftjoin = m.LeftJoin(nullset, new BooleanExpressionTerm(true)); foreach (Set set in leftjoin.Sets) { Console.WriteLine(set.ToString()); } Console.WriteLine(); //Try a Join Console.WriteLine("Join LHS-RHS"); join = m.Join(n); foreach (Set set in join.Sets) { Console.WriteLine(set.ToString()); } Console.WriteLine(); //Try a LeftOuterJoin Console.WriteLine("LeftJoin LHS-RHS"); leftjoin = m.LeftJoin(n, new BooleanExpressionTerm(true)); foreach (Set set in leftjoin.Sets) { Console.WriteLine(set.ToString()); } Console.WriteLine(); //Try a Produce Console.WriteLine("Product LHS-RHS"); BaseMultiset product = m.Product(n); foreach (Set set in product.Sets) { Console.WriteLine(set.ToString()); } Console.WriteLine(); //Try a Join to Self Console.WriteLine("Product LHS-D"); product = m.Product(d); foreach (Set set in product.Sets) { Console.WriteLine(set.ToString()); } Console.WriteLine(); //Try a Union Console.WriteLine("Union LHS-RHS"); BaseMultiset union = m.Union(n); foreach (Set set in union.Sets) { Console.WriteLine(set.ToString()); } Console.WriteLine(); }
/// <summary> /// Processes a COPY command /// </summary> /// <param name="cmd">Copy Command</param> public void ProcessCopyCommand(CopyCommand cmd) { if (this._manager is IUpdateableGenericIOManager) { ((IUpdateableGenericIOManager)this._manager).Update(cmd.ToString()); } else { try { //If Source and Destination are equal this is a no-op if (EqualityHelper.AreUrisEqual(cmd.SourceUri, cmd.DestinationUri)) return; //Firstly check that appropriate IO Behaviour is provided if (cmd.SourceUri == null || cmd.DestinationUri == null) { if ((this._manager.IOBehaviour & IOBehaviour.HasDefaultGraph) == 0) throw new SparqlUpdateException("The underlying store does not provide support for an explicit unnamed Default Graph required to process this command"); } IOBehaviour desired = cmd.DestinationUri == null ? IOBehaviour.OverwriteDefault : IOBehaviour.OverwriteNamed; if ((this._manager.IOBehaviour & desired) == 0) throw new SparqlUpdateException("The underlying store does not provide the required IO Behaviour to implement this command"); Graph source = new Graph(); this._manager.LoadGraph(source, cmd.SourceUri); source.BaseUri = cmd.SourceUri; //If the Manager supports delete ensure the Destination Graph is deleted if (this._manager.DeleteSupported) { try { this._manager.DeleteGraph(cmd.DestinationUri); } catch (Exception ex) { throw new SparqlUpdateException("Unable to process a COPY command as unable to ensure that the Destination Graph was deleted prior to moving the data from the Source Graph", ex); } } //Load Destination Graph and ensure it is empty Graph dest = new Graph(); this._manager.LoadGraph(dest, cmd.DestinationUri); dest.BaseUri = cmd.DestinationUri; dest.Clear(); //Transfer the data and update both the Graphs dest.Merge(source); this._manager.SaveGraph(dest); } catch { if (!cmd.Silent) throw; } } }
/// <summary> /// Processes a Graph. /// </summary> /// <param name="graph">Graph.</param> /// <param name="context">SPARQL Evaluation Context.</param> public override BaseMultiset ProcessGraph(Algebra.Graph graph, SparqlEvaluationContext context) { return(ExplainAndEvaluate <Algebra.Graph>(graph, context, base.ProcessGraph)); }
/// <summary> /// Processes a CREATE command /// </summary> /// <param name="cmd">Create Command</param> /// <remarks> /// <para> /// Implemented by adding an empty Graph to the Store /// </para> /// <para> /// <strong>Warning:</strong> As the <see cref="IGenericIOManager">IGenericIOManager</see> interface does not allow checking whether a Graph exists processing CREATE commands can result in overwriting existing Graphs /// </para> /// </remarks> public void ProcessCreateCommand(CreateCommand cmd) { if (this._manager is IUpdateableGenericIOManager) { ((IUpdateableGenericIOManager)this._manager).Update(cmd.ToString()); } else { Graph g = new Graph(); g.BaseUri = cmd.TargetUri; try { //As Khalil Ahmed pointed out the behaviour when the store doesn't support empty graphs the behaviour should be to act as if the operation succeeded if ((this._manager.IOBehaviour & IOBehaviour.ExplicitEmptyGraphs) == 0) return; this._manager.SaveGraph(g); } catch { if (!cmd.Silent) throw; } } }