Ejemplo n.º 1
0
        /// <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;
            }
        }
Ejemplo n.º 2
0
        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;
            }
        }
Ejemplo n.º 3
0
        /// <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;
            }
        }