public void Apply(SparqlResultSet results) { switch (this._type) { case SparqlResultsType.Boolean: results.SetResult(this._r); break; case SparqlResultsType.VariableBindings: foreach (String var in this._vars) { results.AddVariable(var); } foreach (SparqlResult res in this._results) { results.AddResult(res); } break; default: throw new RdfParseException("The type property of a serialized SparqlResultSet did not contain a valid value"); } }
public void Apply(SparqlResultSet results) { switch (_type) { case SparqlResultsType.Boolean: results.SetResult(_r); break; case SparqlResultsType.VariableBindings: foreach (String var in _vars) { results.AddVariable(var); } foreach (SparqlResult res in _results) { results.AddResult(res); } break; default: throw new RdfParseException("The type property of a serialized SparqlResultSet did not contain a valid value"); } }
/// <summary> /// Handles a Result by adding it to the Result Set. /// </summary> /// <param name="result">Result.</param> /// <returns></returns> protected override bool HandleResultInternal(SparqlResult result) { _results.AddResult(result); return(true); }
/// <summary> /// Executes a SPARQL Query on the native Quad Store /// </summary> /// <param name="sparqlQuery">SPARQL Query to execute</param> /// <returns></returns> /// <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 extensions which the library does not support. These include things like aggregate functions but also SPARQL Update statements. /// </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 Object Query(String sparqlQuery) { Object finalResult = null; 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 if (results.Rows.Count == 1 && results.Columns.Count == 1) { bool result; int r; if (Boolean.TryParse(results.Rows[0][0].ToString(), out result)) { finalResult = new SparqlResultSet(result); } else if (Int32.TryParse(results.Rows[0][0].ToString(), out r)) { if (r == 1) { finalResult = new SparqlResultSet(true); } else { finalResult = new SparqlResultSet(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 finalResult = new SparqlResultSet(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 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(); Graph g = new Graph(); StringParser.Parse(g, data, ttlparser); finalResult = g; } 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: //Expect a DataTable containing columns for each Result Variable and a row for each solution SparqlResultSet rset = new SparqlResultSet(); rset.SetResult(true); //Get Result Variables List<SparqlVariable> resultVars = query.Variables.Where(v => v.IsResultVariable).ToList(); foreach (SparqlVariable var in resultVars) { rset.AddVariable(var.Name); } Graph temp = new Graph(); //Convert each solution into a SPARQLResult foreach (DataRow r in results.Rows) { SparqlResult result = new SparqlResult(); foreach (SparqlVariable var in resultVars) { if (r[var.Name] != null) { result.SetValue(var.Name, this.LoadNode(temp, r[var.Name])); } } rset.AddResult(result); } finalResult = rset; 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) { //No Rows but some columns implies empty SELECT results SparqlResultSet rset = new SparqlResultSet(); foreach (DataColumn col in results.Columns) { rset.AddVariable(col.ColumnName); } finalResult = rset; } 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 finalResult = new SparqlResultSet(); } else if (Boolean.TryParse(results.Rows[0][0].ToString(), out result)) { //Parseable Boolean so ASK Results finalResult = new SparqlResultSet(result); } else if (Int32.TryParse(results.Rows[0][0].ToString(), out r)) { //Parseable Integer so Aggregate SELECT Query Results SparqlResultSet rset = new SparqlResultSet(); rset.AddVariable("Result"); SparqlResult res = new SparqlResult(); res.SetValue("Result", new LiteralNode(null, r.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeInteger))); rset.AddResult(res); finalResult = rset; } else if (Single.TryParse(results.Rows[0][0].ToString(), out rflt)) { //Parseable Single so Aggregate SELECT Query Results SparqlResultSet rset = new SparqlResultSet(); rset.AddVariable("Result"); SparqlResult res = new SparqlResult(); res.SetValue("Result", new LiteralNode(null, rflt.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeFloat))); rset.AddResult(res); finalResult = rset; } else if (Double.TryParse(results.Rows[0][0].ToString(), out rdbl)) { //Parseable Double so Aggregate SELECT Query Results SparqlResultSet rset = new SparqlResultSet(); rset.AddVariable("Result"); SparqlResult res = new SparqlResult(); res.SetValue("Result", new LiteralNode(null, rdbl.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeDouble))); rset.AddResult(res); finalResult = rset; } else if (Decimal.TryParse(results.Rows[0][0].ToString(), out rdec)) { //Parseable Decimal so Aggregate SELECT Query Results SparqlResultSet rset = new SparqlResultSet(); rset.AddVariable("Result"); SparqlResult res = new SparqlResult(); res.SetValue("Result", new LiteralNode(null, rdec.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeDecimal))); rset.AddResult(res); finalResult = rset; } else { //String so try and parse as Turtle try { //Use StringParser to parse String data = results.Rows[0][0].ToString(); TurtleParser ttlparser = new TurtleParser(); Graph g = new Graph(); StringParser.Parse(g, data, ttlparser); finalResult = g; } catch (RdfParseException) { //If it failed to parse then it might be the result of one of the aggregate //functions that Virtuoso extends Sparql with Graph temp = new Graph(); SparqlResultSet rset = new SparqlResultSet(); rset.AddVariable(results.Columns[0].ColumnName); SparqlResult res = new SparqlResult(); res.SetValue(results.Columns[0].ColumnName, this.LoadNode(temp, results.Rows[0][0])); //Nothing was returned here previously - fix submitted by Aleksandr A. Zaripov [[email protected]] rset.AddResult(res); finalResult = rset; } } } 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]] //SELECT Query Results SparqlResultSet rset = new SparqlResultSet(); rset.SetResult(true); //Get Result Variables foreach (DataColumn col in results.Columns) { rset.AddVariable(col.ColumnName); } Graph temp = new Graph(); //Convert each solution into a SPARQLResult foreach (DataRow r in results.Rows) { SparqlResult result = new SparqlResult(); foreach (String var in rset.Variables) { if (r[var] != null) { result.SetValue(var, this.LoadNode(temp, r[var])); } } rset.AddResult(result); } finalResult = rset; } } return finalResult; }