Exemplo n.º 1
0
 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);
 }
Exemplo n.º 4
0
        /// <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;
        }