/// <summary> /// Applies the result set to a Results Handler. /// </summary> /// <param name="handler">Results Handler.</param> /// <param name="results">Result Set.</param> public static void Apply(this ISparqlResultsHandler handler, SparqlResultSet results) { try { handler.StartResults(); switch (results.ResultsType) { case SparqlResultsType.Boolean: handler.HandleBooleanResult(results.Result); break; case SparqlResultsType.VariableBindings: foreach (String var in results.Variables) { if (!handler.HandleVariable(var)) { ParserHelper.Stop(); } } foreach (SparqlResult r in results) { if (!handler.HandleResult(r)) { ParserHelper.Stop(); } } break; default: // Does nothing break; } handler.EndResults(true); } catch (RdfParsingTerminatedException) { handler.EndResults(true); } catch { handler.EndResults(false); throw; } }
/// <summary> /// Makes a Query where the expected Result is a SparqlResultSet ie. SELECT and ASK Queries /// </summary> /// <param name="handler">Results Handler to process the results</param> /// <param name="sparqlQuery">SPARQL Query String</param> /// <exception cref="RdfQueryException">Thrown if any of the requests to the endpoints fail</exception> /// <exception cref="RdfQueryTimeoutException">Thrown if not all the requests complete within the set timeout</exception> public override void QueryWithResultSet(ISparqlResultsHandler handler, string sparqlQuery) { //If no endpoints do nothing if (this._endpoints.Count == 0) { return; } //Fire off all the Asychronous Requests List <AsyncQueryWithResultSet> asyncCalls = new List <AsyncQueryWithResultSet>(); List <IAsyncResult> asyncResults = new List <IAsyncResult>(); int count = 0; foreach (SparqlRemoteEndpoint endpoint in this._endpoints) { //Limit the number of simultaneous requests we make to the user defined level (default 4) //We do this limiting check before trying to issue a request so that when the last request //is issued we'll always drop out of the loop and move onto our WaitAll() while (count >= this._maxSimultaneousRequests) { //First check that the count of active requests is accurate int active = asyncResults.Count(r => !r.IsCompleted); if (active < count) { //Some of the requests have already completed so we don't need to wait count = active; break; } else if (active > count) { //There are more active requests then we thought count = active; } //While the number of requests is at/above the maximum we'll wait for any of the requests to finish //Then we can decrement the count and if this drops back below our maximum then we'll go back into the //main loop and fire off our next request WaitHandle.WaitAny(asyncResults.Select(r => r.AsyncWaitHandle).ToArray()); count--; } //Make an asynchronous query to the next endpoint AsyncQueryWithResultSet d = new AsyncQueryWithResultSet(endpoint.QueryWithResultSet); asyncCalls.Add(d); IAsyncResult asyncResult = d.BeginInvoke(sparqlQuery, null, null); asyncResults.Add(asyncResult); count++; } //Wait for all our requests to finish int waitTimeout = (base.Timeout > 0) ? base.Timeout : System.Threading.Timeout.Infinite; WaitHandle.WaitAll(asyncResults.Select(r => r.AsyncWaitHandle).ToArray(), waitTimeout); //Check for and handle timeouts if (!this._ignoreFailedRequests && !asyncResults.All(r => r.IsCompleted)) { for (int i = 0; i < asyncCalls.Count; i++) { try { asyncCalls[i].EndInvoke(asyncResults[i]); } catch { //Exceptions don't matter as we're just ensuring all the EndInvoke() calls are made } } throw new RdfQueryTimeoutException("Federated Querying failed due to one/more endpoints failing to return results within the Timeout specified which is currently " + (base.Timeout / 1000) + " seconds"); } //Now merge all the results together HashSet <String> varsSeen = new HashSet <string>(); bool cont = true; for (int i = 0; i < asyncCalls.Count; i++) { //Retrieve the result for this call AsyncQueryWithResultSet call = asyncCalls[i]; SparqlResultSet partialResult; try { partialResult = call.EndInvoke(asyncResults[i]); } catch (Exception ex) { if (!this._ignoreFailedRequests) { //Clean up in the event of an error for (int j = i + 1; j < asyncCalls.Count; j++) { try { asyncCalls[j].EndInvoke(asyncResults[j]); } catch { //Exceptions don't matter as we're just ensuring all the EndInvoke() calls are made } } //If a single request fails then the entire query fails throw new RdfQueryException("Federated Querying failed due to the query against the endpoint '" + this._endpoints[i].Uri.ToString() + "' failing", ex); } else { //If we're ignoring failed requests we continue here continue; } } //Merge the result into the final results //If the handler has previously told us to stop we skip this step if (cont) { foreach (String variable in partialResult.Variables) { cont = handler.HandleVariable(variable); //Stop if handler tells us to if (!cont) { break; } } if (cont) { foreach (SparqlResult result in partialResult.Results) { cont = handler.HandleResult(result); //Stop if handler tells us to if (!cont) { break; } } } } } }
internal static void Apply(this ISparqlResultsHandler handler, SparqlEvaluationContext context) { try { handler.StartResults(); SparqlQuery q = context.Query; SparqlQueryType type; if (q == null) { type = (context.OutputMultiset.Variables.Any() || context.OutputMultiset.Sets.Any() ? SparqlQueryType.Select : SparqlQueryType.Ask); } else { type = q.QueryType; } if (type == SparqlQueryType.Ask) { //ASK Query so get the handler to handle an appropriate boolean result if (context.OutputMultiset is IdentityMultiset) { handler.HandleBooleanResult(true); } else if (context.OutputMultiset is NullMultiset) { handler.HandleBooleanResult(false); } else { handler.HandleBooleanResult(!context.OutputMultiset.IsEmpty); } } else { //SELECT Query so get the handler to handle variables and then handle results foreach (String var in context.OutputMultiset.Variables) { if (!handler.HandleVariable(var)) { ParserHelper.Stop(); } } foreach (ISet s in context.OutputMultiset.Sets) { if (!handler.HandleResult(new SparqlResult(s))) { ParserHelper.Stop(); } } q.VirtualCount = context.OutputMultiset.VirtualCount; } handler.EndResults(true); } catch (RdfParsingTerminatedException) { handler.EndResults(true); } catch { handler.EndResults(false); throw; } }
/// <summary> /// Makes a Query where the expected Result is a SparqlResultSet ie. SELECT and ASK Queries. /// </summary> /// <param name="handler">Results Handler to process the results.</param> /// <param name="sparqlQuery">SPARQL Query String.</param> /// <exception cref="RdfQueryException">Thrown if any of the requests to the endpoints fail.</exception> /// <exception cref="RdfQueryTimeoutException">Thrown if not all the requests complete within the set timeout.</exception> public override void QueryWithResultSet(ISparqlResultsHandler handler, string sparqlQuery) { // If no endpoints do nothing if (_endpoints.Count == 0) { return; } // Fire off all the asynchronous Requests var asyncCalls = new List <Task <SparqlResultSet> >(); var cts = new CancellationTokenSource(); int count = 0; foreach (SparqlRemoteEndpoint endpoint in _endpoints) { // Limit the number of simultaneous requests we make to the user defined level (default 4) // We do this limiting check before trying to issue a request so that when the last request // is issued we'll always drop out of the loop and move onto our WaitAll() while (count >= _maxSimultaneousRequests) { // First check that the count of active requests is accurate int active = asyncCalls.Count(r => !r.IsCompleted); if (active < count) { // Some of the requests have already completed so we don't need to wait count = active; break; } if (active > count) { // There are more active requests then we thought count = active; } // While the number of requests is at/above the maximum we'll wait for any of the requests to finish // Then we can decrement the count and if this drops back below our maximum then we'll go back into the // main loop and fire off our next request Task.WaitAny(asyncCalls.ToArray(), cts.Token); count--; } // Make an asynchronous query to the next endpoint asyncCalls.Add(Task.Factory.StartNew(() => endpoint.QueryWithResultSet(sparqlQuery), cts.Token)); count++; } // Wait for all our requests to finish int waitTimeout = (Timeout > 0) ? Timeout : System.Threading.Timeout.Infinite; try { if (!Task.WaitAll(asyncCalls.ToArray(), waitTimeout, cts.Token)) { // Handle timeouts - cancel overrunning tasks and optionally throw an exception cts.Cancel(false); if (!_ignoreFailedRequests) { throw new RdfQueryTimeoutException( "Federated Querying failed due to one/more endpoints failing to return results within the Timeout specified which is currently " + (Timeout / 1000) + " seconds"); } } } catch (AggregateException ex) { if (!_ignoreFailedRequests) { // Try to determine which endpoint faulted var faultedTaskIndex = asyncCalls.FindIndex(t => t.IsFaulted); var faultedEndpointUri = _endpoints[faultedTaskIndex].Uri.AbsoluteUri; throw new RdfQueryException( "Federated querying failed due to the query against the endpoint '" + faultedEndpointUri + "' failing.", ex.InnerException); } } // Now merge all the results together var cont = true; for (var i = 0; i < asyncCalls.Count; i++) { if (!asyncCalls[i].IsCompleted) { // This is a timed out task that has not transitioned to cancelled state yet // We will only get here if _ignoreFailedRequests is true continue; } // Retrieve the result for this call SparqlResultSet partialResult; try { partialResult = asyncCalls[i].Result; } catch (Exception ex) { if (!_ignoreFailedRequests) { // If a single request fails then the entire query fails throw new RdfQueryException( "Federated querying failed due to the query against the endpoint '" + _endpoints[i].Uri.AbsoluteUri + "' failing", ex); } // If we're ignoring failed requests we continue here continue; } // Merge the result into the final results // If the handler has previously told us to stop we skip this step if (cont) { handler.StartResults(); foreach (var variable in partialResult.Variables) { cont = handler.HandleVariable(variable); // Stop if handler tells us to if (!cont) { break; } } if (cont) { foreach (var result in partialResult.Results) { cont = handler.HandleResult(result); // Stop if handler tells us to if (!cont) { break; } } } handler.EndResults(cont); } } }
/// <summary> /// Makes a Query where the expected Result is a SparqlResultSet ie. SELECT and ASK Queries /// </summary> /// <param name="handler">Results Handler to process the results</param> /// <param name="sparqlQuery">SPARQL Query String</param> /// <exception cref="RdfQueryException">Thrown if any of the requests to the endpoints fail</exception> /// <exception cref="RdfQueryTimeoutException">Thrown if not all the requests complete within the set timeout</exception> public override void QueryWithResultSet(ISparqlResultsHandler handler, string sparqlQuery) { //If no endpoints do nothing if (this._endpoints.Count == 0) return; //Fire off all the Asychronous Requests List<AsyncQueryWithResultSet> asyncCalls = new List<AsyncQueryWithResultSet>(); List<IAsyncResult> asyncResults = new List<IAsyncResult>(); int count = 0; foreach (SparqlRemoteEndpoint endpoint in this._endpoints) { //Limit the number of simultaneous requests we make to the user defined level (default 4) //We do this limiting check before trying to issue a request so that when the last request //is issued we'll always drop out of the loop and move onto our WaitAll() while (count >= this._maxSimultaneousRequests) { //First check that the count of active requests is accurate int active = asyncResults.Count(r => !r.IsCompleted); if (active < count) { //Some of the requests have already completed so we don't need to wait count = active; break; } else if (active > count) { //There are more active requests then we thought count = active; } //While the number of requests is at/above the maximum we'll wait for any of the requests to finish //Then we can decrement the count and if this drops back below our maximum then we'll go back into the //main loop and fire off our next request WaitHandle.WaitAny(asyncResults.Select(r => r.AsyncWaitHandle).ToArray()); count--; } //Make an asynchronous query to the next endpoint AsyncQueryWithResultSet d = new AsyncQueryWithResultSet(endpoint.QueryWithResultSet); asyncCalls.Add(d); IAsyncResult asyncResult = d.BeginInvoke(sparqlQuery, null, null); asyncResults.Add(asyncResult); count++; } //Wait for all our requests to finish int waitTimeout = (base.Timeout > 0) ? base.Timeout : System.Threading.Timeout.Infinite; WaitHandle.WaitAll(asyncResults.Select(r => r.AsyncWaitHandle).ToArray(), waitTimeout); //Check for and handle timeouts if (!this._ignoreFailedRequests && !asyncResults.All(r => r.IsCompleted)) { for (int i = 0; i < asyncCalls.Count; i++) { try { asyncCalls[i].EndInvoke(asyncResults[i]); } catch { //Exceptions don't matter as we're just ensuring all the EndInvoke() calls are made } } throw new RdfQueryTimeoutException("Federated Querying failed due to one/more endpoints failing to return results within the Timeout specified which is currently " + (base.Timeout / 1000) + " seconds"); } //Now merge all the results together HashSet<String> varsSeen = new HashSet<string>(); bool cont = true; for (int i = 0; i < asyncCalls.Count; i++) { //Retrieve the result for this call AsyncQueryWithResultSet call = asyncCalls[i]; SparqlResultSet partialResult; try { partialResult = call.EndInvoke(asyncResults[i]); } catch (Exception ex) { if (!this._ignoreFailedRequests) { //Clean up in the event of an error for (int j = i + 1; j < asyncCalls.Count; j++) { try { asyncCalls[j].EndInvoke(asyncResults[j]); } catch { //Exceptions don't matter as we're just ensuring all the EndInvoke() calls are made } } //If a single request fails then the entire query fails throw new RdfQueryException("Federated Querying failed due to the query against the endpoint '" + this._endpoints[i].Uri.ToString() + "' failing", ex); } else { //If we're ignoring failed requests we continue here continue; } } //Merge the result into the final results //If the handler has previously told us to stop we skip this step if (cont) { foreach (String variable in partialResult.Variables) { cont = handler.HandleVariable(variable); //Stop if handler tells us to if (!cont) break; } if (cont) { foreach (SparqlResult result in partialResult.Results) { cont = handler.HandleResult(result); //Stop if handler tells us to if (!cont) break; } } } } }
/// <summary> /// Executes a SPARQL Query on the native Quad Store processing the results with an appropriate handler from those provided /// </summary> /// <param name="rdfHandler">RDF Handler</param> /// <param name="resultsHandler">Results Handler</param> /// <param name="sparqlQuery">SPARQL Query to execute</param> /// <remarks> /// <para> /// This method will first attempt to parse the query into a <see cref="SparqlQuery">SparqlQuery</see> object. If this succeeds then the Query Type can be used to determine how to handle the response. /// </para> /// <para> /// If the parsing fails then the query will be executed anyway using Virtuoso's SPASQL (SPARQL + SQL) syntax. Parsing can fail because Virtuoso supports various SPARQL non-standardised extensions which the library does not support. These include things like aggregate functions but also SPARUL updates (the non-standard precusor to SPARQL 1.1 Update). /// </para> /// <para> /// If you use an aggregate query which has an Integer, Decimal or Double type result then you will receive a <see cref="SparqlResultSet">SparqlResultSet</see> containing a single <see cref="SparqlResult">SparqlResult</see> which has contains a binding for a variable named <strong>Result</strong> which contains a <see cref="LiteralNode">LiteralNode</see> typed to the appropriate datatype. /// </para> /// </remarks> /// <exception cref="RdfQueryException">Thrown if an error occurs in making the query</exception> public void Query(IRdfHandler rdfHandler, ISparqlResultsHandler resultsHandler, String sparqlQuery) { try { if (resultsHandler != null) resultsHandler.StartResults(); DataTable results = new DataTable(); results.Columns.CollectionChanged += new System.ComponentModel.CollectionChangeEventHandler(Columns_CollectionChanged); //See if the query can be parsed into a SparqlQuery object //It might not since the user might use Virtuoso's extensions to Sparql in their query try { //We'll set the Parser to SPARQL 1.1 mode even though Virtuoso's SPARQL implementation has //various perculiarties in their SPARQL 1.1 implementation and we'll try and //handle the potential results in the catch branch if a valid SPARQL 1.0 query //cannot be parsed //Change made in response to a bug report by Aleksandr A. Zaripov [[email protected]] SparqlQueryParser parser = new SparqlQueryParser(); parser.SyntaxMode = SparqlQuerySyntax.Sparql_1_1; SparqlQuery query = parser.ParseFromString(sparqlQuery); switch (query.QueryType) { case SparqlQueryType.Select: case SparqlQueryType.SelectAll: case SparqlQueryType.SelectAllDistinct: case SparqlQueryType.SelectAllReduced: case SparqlQueryType.SelectDistinct: case SparqlQueryType.SelectReduced: //Type the Tables columns as System.Object foreach (SparqlVariable var in query.Variables) { if (var.IsResultVariable) { results.Columns.Add(var.Name, typeof(System.Object)); } } break; } try { this.Open(false); //Make the Query against Virtuoso VirtuosoCommand cmd = this._db.CreateCommand(); cmd.CommandText = "SPARQL " + sparqlQuery; VirtuosoDataAdapter adapter = new VirtuosoDataAdapter(cmd); adapter.Fill(results); //Decide how to process the results based on the return type switch (query.QueryType) { case SparqlQueryType.Ask: //Expect a DataTable containing a single row and column which contains a boolean //Ensure Results Handler is not null if (resultsHandler == null) throw new ArgumentNullException("Cannot handle a Boolean Result with a null SPARQL Results Handler"); if (results.Rows.Count == 1 && results.Columns.Count == 1) { //Try and parse the result bool result; int r; if (Boolean.TryParse(results.Rows[0][0].ToString(), out result)) { resultsHandler.HandleBooleanResult(result); } else if (Int32.TryParse(results.Rows[0][0].ToString(), out r)) { if (r == 1) { resultsHandler.HandleBooleanResult(true); } else { resultsHandler.HandleBooleanResult(false); } } else { throw new RdfQueryException("Expected a Boolean as the result of an ASK query but the non-boolean value '" + results.Rows[0][0].ToString() + "' was received"); } } else { //If we get anything else then we'll return that the result was False resultsHandler.HandleBooleanResult(false); } break; case SparqlQueryType.Construct: case SparqlQueryType.Describe: case SparqlQueryType.DescribeAll: //Expect a DataTable containing a single row and column which contains a String //That string will be a Turtle serialization of the Graph //Ensure that RDF Handler is not null if (rdfHandler == null) throw new ArgumentNullException("Cannot handle a Graph result with a null RDF Handler"); if (results.Rows.Count == 1 && results.Columns.Count == 1) { try { //Use StringParser to parse String data = results.Rows[0][0].ToString(); TurtleParser ttlparser = new TurtleParser(); ttlparser.Load(rdfHandler, new StringReader(data)); } catch (RdfParseException parseEx) { throw new RdfQueryException("Expected a valid Turtle serialization of the Graph resulting from a CONSTRUCT/DESCRIBE query but the result failed to parse", parseEx); } } else { throw new RdfQueryException("Expected a single string value representing the serialization of the Graph resulting from a CONSTRUCT/DESCRIBE query but this was not received"); } break; case SparqlQueryType.Select: case SparqlQueryType.SelectAll: case SparqlQueryType.SelectAllDistinct: case SparqlQueryType.SelectAllReduced: case SparqlQueryType.SelectDistinct: case SparqlQueryType.SelectReduced: //Ensure Results Handler is not null if (resultsHandler == null) throw new ArgumentNullException("Cannot handle SPARQL Results with a null Results Handler"); //Get Result Variables List<SparqlVariable> resultVars = query.Variables.Where(v => v.IsResultVariable).ToList(); foreach (SparqlVariable var in resultVars) { if (!resultsHandler.HandleVariable(var.Name)) ParserHelper.Stop(); } Graph temp = new Graph(); //Convert each solution into a SPARQLResult foreach (DataRow r in results.Rows) { Set s = new Set(); foreach (SparqlVariable var in resultVars) { if (r[var.Name] != null) { s.Add(var.Name, this.LoadNode(temp, r[var.Name])); } } if (!resultsHandler.HandleResult(new SparqlResult(s))) ParserHelper.Stop(); } break; default: throw new RdfQueryException("Unable to process the Results of an Unknown query type"); } this.Close(false); } catch { this.Close(true, true); throw; } } catch (RdfParseException) { //Unable to parse a SPARQL 1.0 query //Have to attempt to detect the return type based on the DataTable that //the SPASQL (Sparql+SQL) query gives back //Make the Query against Virtuoso VirtuosoCommand cmd = this._db.CreateCommand(); cmd.CommandText = "SPARQL " /*define output:format '_JAVA_' "*/ + sparqlQuery; VirtuosoDataAdapter adapter = new VirtuosoDataAdapter(cmd); adapter.Fill(results); //Try to detect the return type based on the DataTable configuration if (results.Rows.Count == 0 && results.Columns.Count > 0) { if (resultsHandler == null) throw new ArgumentNullException("Cannot handler SPARQL Results with a null Results Handler"); //No Rows but some columns implies empty SELECT results SparqlResultSet rset = new SparqlResultSet(); foreach (DataColumn col in results.Columns) { if (!resultsHandler.HandleVariable(col.ColumnName)) ParserHelper.Stop(); } } else if (results.Rows.Count == 1 && results.Columns.Count == 1 && !Regex.IsMatch(sparqlQuery, "SELECT", RegexOptions.IgnoreCase)) { //Added a fix here suggested by Alexander Sidorov - not entirely happy with this fix as what happens if SELECT just happens to occur in a URI/Variable Name? //Single Row and Column implies ASK/DESCRIBE/CONSTRUCT results bool result; int r; decimal rdec; double rdbl; float rflt; if (results.Rows[0][0].ToString().Equals(String.Empty)) { //Empty Results - no need to do anything } else if (Boolean.TryParse(results.Rows[0][0].ToString(), out result)) { //Parseable Boolean so ASK Results if (resultsHandler == null) throw new ArgumentNullException("Cannot handle a Boolean result with a null Results Handler"); resultsHandler.HandleBooleanResult(result); } else if (Int32.TryParse(results.Rows[0][0].ToString(), out r)) { if (resultsHandler == null) throw new ArgumentNullException("Cannot handle SPARQL results with a null Results Handler"); //Parseable Integer so Aggregate SELECT Query Results if (!resultsHandler.HandleVariable("Result")) ParserHelper.Stop(); Set s = new Set(); s.Add("Result", resultsHandler.CreateLiteralNode(r.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeInteger))); if (!resultsHandler.HandleResult(new SparqlResult(s))) ParserHelper.Stop(); } else if (Single.TryParse(results.Rows[0][0].ToString(), out rflt)) { if (resultsHandler == null) throw new ArgumentNullException("Cannot handle SPARQL results with a null Results Handler"); //Parseable Single so Aggregate SELECT Query Results if (!resultsHandler.HandleVariable("Result")) ParserHelper.Stop(); Set s = new Set(); s.Add("Result", resultsHandler.CreateLiteralNode(rflt.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeFloat))); if (!resultsHandler.HandleResult(new SparqlResult(s))) ParserHelper.Stop(); } else if (Double.TryParse(results.Rows[0][0].ToString(), out rdbl)) { if (resultsHandler == null) throw new ArgumentNullException("Cannot handle SPARQL results with a null Results Handler"); //Parseable Double so Aggregate SELECT Query Results if (!resultsHandler.HandleVariable("Result")) ParserHelper.Stop(); Set s = new Set(); s.Add("Result", resultsHandler.CreateLiteralNode(rdbl.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeDouble))); if (!resultsHandler.HandleResult(new SparqlResult(s))) ParserHelper.Stop(); } else if (Decimal.TryParse(results.Rows[0][0].ToString(), out rdec)) { //Parseable Decimal so Aggregate SELECT Query Results if (!resultsHandler.HandleVariable("Result")) ParserHelper.Stop(); Set s = new Set(); s.Add("Result", resultsHandler.CreateLiteralNode(rdec.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeDecimal))); if (!resultsHandler.HandleResult(new SparqlResult(s))) ParserHelper.Stop(); } else { //String so try and parse as Turtle try { //Use StringParser to parse String data = results.Rows[0][0].ToString(); TurtleParser ttlparser = new TurtleParser(); ttlparser.Load(rdfHandler, new StringReader(data)); } catch (RdfParseException) { if (resultsHandler == null) throw new ArgumentNullException("Cannot handle SPARQL results with a null Results Handler"); //If it failed to parse then it might be the result of one of the aggregate //functions that Virtuoso extends Sparql with if (!resultsHandler.HandleVariable(results.Columns[0].ColumnName)) ParserHelper.Stop(); Set s = new Set(); s.Add(results.Columns[0].ColumnName, this.LoadNode(resultsHandler, results.Rows[0][0])); //Nothing was returned here previously - fix submitted by Aleksandr A. Zaripov [[email protected]] if (!resultsHandler.HandleResult(new SparqlResult(s))) ParserHelper.Stop(); } } } else { //Any other number of rows/columns we have to assume that it's normal SELECT results //Changed in response to bug report by Aleksandr A. Zaripov [[email protected]] if (resultsHandler == null) throw new ArgumentNullException("Cannot handle SPARQL results with a null Results Handler"); //Get Result Variables List<String> vars = new List<string>(); foreach (DataColumn col in results.Columns) { vars.Add(col.ColumnName); if (!resultsHandler.HandleVariable(col.ColumnName)) ParserHelper.Stop(); } //Convert each solution into a SPARQLResult foreach (DataRow r in results.Rows) { Set s = new Set(); foreach (String var in vars) { if (r[var] != null) { s.Add(var, this.LoadNode(resultsHandler, r[var])); } } if (!resultsHandler.HandleResult(new SparqlResult(s))) ParserHelper.Stop(); } } } if (resultsHandler != null) resultsHandler.EndResults(true); } catch (RdfParsingTerminatedException) { if (resultsHandler != null) resultsHandler.EndResults(true); } catch { if (resultsHandler != null) resultsHandler.EndResults(false); throw; } }