/// <summary> /// Constructs a Node based on the given Set. /// </summary> /// <param name="context">Construct Context.</param> /// <returns>The Node which is bound to this Variable in this Solution.</returns> protected internal override INode Construct(ConstructContext context) { INode value = context.Set[_varname]; if (value == null) { throw new RdfQueryException("Unable to construct a Value for this Variable for this solution as it is bound to a null"); } switch (value.NodeType) { case NodeType.Blank: if (!context.PreserveBlankNodes && value.GraphUri != null) { // Rename Blank Node based on the Graph Uri Hash Code int hash = value.GraphUri.GetEnhancedHashCode(); if (hash >= 0) { return(new BlankNode(context.Graph, ((IBlankNode)value).InternalID + "-" + value.GraphUri.GetEnhancedHashCode())); } else { return(new BlankNode(context.Graph, ((IBlankNode)value).InternalID + hash)); } } else { return(new BlankNode(context.Graph, ((IBlankNode)value).InternalID)); } default: return(context.GetNode(value)); } }
/// <summary> /// Returns a Blank Node with a fixed ID scoped to whichever graph is provided /// </summary> /// <param name="context">Construct Context</param> protected internal override INode Construct(ConstructContext context) { if (context.Graph != null) { IBlankNode b = context.Graph.GetBlankNode(_id); if (b != null) { return(b); } else { return(context.Graph.CreateBlankNode(_id)); } } else { return(new BlankNode(context.Graph, _id)); } }
/// <summary> /// Evaluates the Command in the given Context /// </summary> /// <param name="context">Evaluation Context</param> public override void Evaluate(SparqlUpdateEvaluationContext context) { //Split the Pattern into the set of Graph Patterns List <GraphPattern> patterns = new List <GraphPattern>(); if (this._pattern.IsGraph) { patterns.Add(this._pattern); } else if (this._pattern.TriplePatterns.Count > 0 || this._pattern.HasChildGraphPatterns) { if (this._pattern.TriplePatterns.Count > 0) { patterns.Add(new GraphPattern()); this._pattern.TriplePatterns.ForEach(tp => patterns[0].AddTriplePattern(tp)); } this._pattern.ChildGraphPatterns.ForEach(gp => patterns.Add(gp)); } else { //If no Triple Patterns and No Child Graph Patterns nothing to do return; } ConstructContext constructContext = new ConstructContext(null, null, false); foreach (GraphPattern pattern in patterns) { if (!this.IsValidDataPattern(pattern, false)) { throw new SparqlUpdateException("Cannot evaluate a INSERT DATA command where any of the Triple Patterns are not concrete triples (variables are not permitted) or any of the GRAPH clauses have nested Graph Patterns"); } //Get the Target Graph IGraph target; Uri graphUri; 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"); } } else { graphUri = null; } if (context.Data.HasGraph(graphUri)) { target = context.Data.GetModifiableGraph(graphUri); } else { //If the Graph does not exist then it must be created target = new Graph(); target.BaseUri = graphUri; context.Data.AddGraph(target); } //Insert the actual Triples foreach (IConstructTriplePattern p in pattern.TriplePatterns.OfType <IConstructTriplePattern>()) { INode subj = p.Subject.Construct(constructContext); INode pred = p.Predicate.Construct(constructContext); INode obj = p.Object.Construct(constructContext); target.Assert(new Triple(subj, pred, obj, graphUri)); } } }
/// <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 (results is IdentityMultiset) { queryContext.OutputMultiset = new SingletonMultiset(results.Variables); } 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 query fails for any reason context.Data.ResetActiveGraph(); datasetOk = false; } //Reset Active Graph for the WHERE if (defGraphOk) { context.Data.ResetActiveGraph(); defGraphOk = false; } //TODO: Need to detect when we create a Graph for Insertion but then fail to insert anything since in this case the Inserted Graph should be removed //Get the Graph to which we are inserting Triples with no explicit Graph clause IGraph g = null; if (this._insertPattern.TriplePatterns.Count > 0) { if (context.Data.HasGraph(this._graphUri)) { g = context.Data.GetModifiableGraph(this._graphUri); } else { //insertedGraphs.Add(this._graphUri); g = new Graph(); g.BaseUri = this._graphUri; context.Data.AddGraph(g); g = context.Data.GetModifiableGraph(this._graphUri); } } //Keep a record of graphs to which we insert MultiDictionary <Uri, IGraph> graphs = new MultiDictionary <Uri, IGraph>(u => (u != null ? u.GetEnhancedHashCode() : 0), true, new UriComparer(), MultiDictionaryMode.AVL); //Insert the Triples for each Solution foreach (ISet s in queryContext.OutputMultiset.Sets) { List <Triple> insertedTriples = new List <Triple>(); try { //Create a new Construct Context for each Solution ConstructContext constructContext = new ConstructContext(null, s, true); //Triples from raw Triple Patterns if (this._insertPattern.TriplePatterns.Count > 0) { foreach (IConstructTriplePattern p in this._insertPattern.TriplePatterns.OfType <IConstructTriplePattern>()) { try { insertedTriples.Add(p.Construct(constructContext)); } catch (RdfQueryException) { //If we throw an error this means we couldn't construct a specific Triple //so we continue anyway } } g.Assert(insertedTriples); } //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: String graphVar = gp.GraphSpecifier.Value.Substring(1); if (s.ContainsVariable(graphVar)) { INode temp = s[graphVar]; 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 (graphs.ContainsKey(destUri)) { h = graphs[destUri]; } else { if (context.Data.HasGraph(destUri)) { h = context.Data.GetModifiableGraph(destUri); } else { //insertedGraphs.Add(destUri); h = new Graph(); h.BaseUri = destUri; context.Data.AddGraph(h); h = context.Data.GetModifiableGraph(destUri); } graphs.Add(destUri, h); } //Do the actual Insertions foreach (IConstructTriplePattern p in gp.TriplePatterns.OfType <IConstructTriplePattern>()) { try { insertedTriples.Add(p.Construct(constructContext)); } catch (RdfQueryException) { //If we throw an error this means we couldn't construct a specific Triple //so we continue anyway } } h.Assert(insertedTriples); } catch (RdfQueryException) { //If we throw an error this means we couldn't construct for this solution so the //solution is ignored for this Graph } } } catch (RdfQueryException) { //If we throw an error 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> /// Constructs a Node based on the given Set /// </summary> /// <param name="context">Construct Context</param> protected internal override INode Construct(ConstructContext context) { return(context.GetNode(this._node)); }
/// <summary> /// Constructs a Node based on this Pattern for the given Set /// </summary> /// <param name="context">Construct Context</param> /// <returns></returns> protected internal abstract INode Construct(ConstructContext context);
/// <summary> /// Constructs a Triple from a Set based on this Triple Pattern. /// </summary> /// <param name="context">Construct Context.</param> /// <returns></returns> public Triple Construct(ConstructContext context) { return(new Triple(Tools.CopyNode(_subj.Construct(context), context.Graph), Tools.CopyNode(_pred.Construct(context), context.Graph), Tools.CopyNode(_obj.Construct(context), context.Graph))); }
/// <summary> /// Processes a SPARQL Query sending the results to a RDF/SPARQL Results handler as appropriate /// </summary> /// <param name="rdfHandler">RDF Handler</param> /// <param name="resultsHandler">Results Handler</param> /// <param name="query">SPARQL Query</param> public void ProcessQuery(IRdfHandler rdfHandler, ISparqlResultsHandler resultsHandler, SparqlQuery query) { //Do Handler null checks before evaluating the query if (query == null) { throw new ArgumentNullException("query", "Cannot evaluate a null query"); } if (rdfHandler == null && (query.QueryType == SparqlQueryType.Construct || query.QueryType == SparqlQueryType.Describe || query.QueryType == SparqlQueryType.DescribeAll)) { throw new ArgumentNullException("rdfHandler", "Cannot use a null RDF Handler when the Query is a CONSTRUCT/DESCRIBE"); } if (resultsHandler == null && (query.QueryType == SparqlQueryType.Ask || SparqlSpecsHelper.IsSelectQuery(query.QueryType))) { throw new ArgumentNullException("resultsHandler", "Cannot use a null resultsHandler when the Query is an ASK/SELECT"); } //Handle the Thread Safety of the Query Evaluation #if !NO_RWLOCK ReaderWriterLockSlim currLock = (this._dataset is IThreadSafeDataset) ? ((IThreadSafeDataset)this._dataset).Lock : this._lock; try { currLock.EnterReadLock(); #endif //Reset Query Timers query.QueryExecutionTime = null; bool datasetOk = false, defGraphOk = false; try { //Set up the Default and Active Graphs if (query.DefaultGraphs.Any()) { //Call HasGraph() on each Default Graph but ignore the results, we just do this //in case a dataset has any kind of load on demand behaviour foreach (Uri defGraphUri in query.DefaultGraphs) { this._dataset.HasGraph(defGraphUri); } this._dataset.SetDefaultGraph(query.DefaultGraphs); defGraphOk = true; } else if (query.NamedGraphs.Any()) { //No FROM Clauses but one/more FROM NAMED means the Default Graph is the empty graph this._dataset.SetDefaultGraph(Enumerable.Empty <Uri>()); } this._dataset.SetActiveGraph(this._dataset.DefaultGraphUris); datasetOk = true; //Convert to Algebra and execute the Query SparqlEvaluationContext context = this.GetContext(query); BaseMultiset result; try { context.StartExecution(); ISparqlAlgebra algebra = query.ToAlgebra(); result = context.Evaluate(algebra); context.EndExecution(); query.QueryExecutionTime = new TimeSpan(context.QueryTimeTicks); } catch (RdfQueryException) { context.EndExecution(); query.QueryExecutionTime = new TimeSpan(context.QueryTimeTicks); throw; } catch { context.EndExecution(); query.QueryExecutionTime = new TimeSpan(context.QueryTimeTicks); throw; } //Return the Results switch (query.QueryType) { case SparqlQueryType.Ask: case SparqlQueryType.Select: case SparqlQueryType.SelectAll: case SparqlQueryType.SelectAllDistinct: case SparqlQueryType.SelectAllReduced: case SparqlQueryType.SelectDistinct: case SparqlQueryType.SelectReduced: //For SELECT and ASK can populate a Result Set directly from the Evaluation Context //return new SparqlResultSet(context); resultsHandler.Apply(context); break; case SparqlQueryType.Construct: //Create a new Empty Graph for the Results try { rdfHandler.StartRdf(); foreach (String prefix in query.NamespaceMap.Prefixes) { if (!rdfHandler.HandleNamespace(prefix, query.NamespaceMap.GetNamespaceUri(prefix))) { ParserHelper.Stop(); } } //Construct the Triples for each Solution foreach (ISet s in context.OutputMultiset.Sets) { //List<Triple> constructedTriples = new List<Triple>(); try { ConstructContext constructContext = new ConstructContext(rdfHandler, s, false); foreach (IConstructTriplePattern p in query.ConstructTemplate.TriplePatterns.OfType <IConstructTriplePattern>()) { try { if (!rdfHandler.HandleTriple(p.Construct(constructContext))) { ParserHelper.Stop(); } //constructedTriples.Add(((IConstructTriplePattern)p).Construct(constructContext)); } catch (RdfQueryException) { //If we get an error here then we could not construct a specific triple //so we continue anyway } } } catch (RdfQueryException) { //If we get an error here this means we couldn't construct for this solution so the //entire solution is discarded continue; } //h.Assert(constructedTriples); } rdfHandler.EndRdf(true); } catch (RdfParsingTerminatedException) { rdfHandler.EndRdf(true); } catch { rdfHandler.EndRdf(false); throw; } break; case SparqlQueryType.Describe: case SparqlQueryType.DescribeAll: //For DESCRIBE we retrieve the Describe algorithm and apply it ISparqlDescribe describer = query.Describer; describer.Describe(rdfHandler, context); break; default: throw new RdfQueryException("Unknown query types cannot be processed by Leviathan"); } } finally { if (defGraphOk) { this._dataset.ResetDefaultGraph(); } if (datasetOk) { this._dataset.ResetActiveGraph(); } } #if !NO_RWLOCK } finally { currLock.ExitReadLock(); } #endif }
/// <summary> /// Evaluates the Command in the given Context /// </summary> /// <param name="context">Evaluation Context</param> public override void Evaluate(SparqlUpdateEvaluationContext context) { bool defGraphOk = false; bool datasetOk = 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 based upon the WITH clause //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/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 (results is IdentityMultiset) { results = new SingletonMultiset(results.Variables); } 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 from which we are deleting IGraph g = context.Data.GetModifiableGraph(this._graphUri); //Delete the Triples for each Solution foreach (ISet s in results.Sets) { List <Triple> deletedTriples = new List <Triple>(); //Triples from raw Triple Patterns try { 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 throw an error this means we couldn't construct for this solution so the //solution is ignored 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: String graphVar = gp.GraphSpecifier.Value.Substring(1); if (s.ContainsVariable(graphVar)) { INode temp = s[graphVar]; 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 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> /// Constructs a Node based on the given Set. /// </summary> /// <param name="context">Construct Context.</param> /// <returns></returns> protected internal override INode Construct(ConstructContext context) { return(context.GetBlankNode(_name)); }