Esempio n. 1
0
        /// <summary>
        /// Evaluates the BGP against the Evaluation Context
        /// </summary>
        /// <param name="context">Evaluation Context</param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            bool         halt;
            BaseMultiset results;
            int          origRequired = this._requiredResults;

            //May need to detect the actual
            if (this._requiredResults < 0)
            {
                if (context.Query != null)
                {
                    if (context.Query.HasDistinctModifier || (context.Query.OrderBy != null && !context.Query.IsOptimisableOrderBy) || context.Query.GroupBy != null || context.Query.Having != null || context.Query.Bindings != null)
                    {
                        //If there's an DISTINCT/ORDER BY/GROUP BY/HAVING/BINDINGS present then can't do Lazy evaluation
                        this._requiredResults = -1;
                    }
                    else
                    {
                        int limit  = context.Query.Limit;
                        int offset = context.Query.Offset;
                        if (limit >= 0 && offset >= 0)
                        {
                            //If there is a Limit and Offset specified then the required results is the LIMIT+OFFSET
                            this._requiredResults = limit + offset;
                        }
                        else if (limit >= 0)
                        {
                            //If there is just a Limit specified then the required results is the LIMIT
                            this._requiredResults = limit;
                        }
                        else
                        {
                            //In any other case required results is everything i.e. -1
                            this._requiredResults = -1;
                        }
                    }
                }
            }

            if (this._requiredResults != 0)
            {
                results = this.StreamingEvaluate(context, 0, out halt);
                if (results is Multiset && results.IsEmpty)
                {
                    results = new NullMultiset();
                }
            }
            else
            {
                results = new NullMultiset();
            }
            this._requiredResults = origRequired;

            context.OutputMultiset = results;
            context.OutputMultiset.Trim();
            return(context.OutputMultiset);
        }
Esempio n. 2
0
        /// <summary>
        /// Evaluates the BGP against the Evaluation Context
        /// </summary>
        /// <param name="context">Evaluation Context</param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            bool         halt;
            BaseMultiset results = this.StreamingEvaluate(context, 0, out halt);

            if (results is Multiset && results.IsEmpty)
            {
                results = new NullMultiset();
            }

            context.OutputMultiset = results;
            context.OutputMultiset.Trim();
            return(context.OutputMultiset);
        }
Esempio n. 3
0
        /// <summary>
        /// Evaluates the Graph Clause by setting up the dataset, applying the pattern and then generating additional bindings if necessary
        /// </summary>
        /// <param name="context">Evaluation Context</param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            // Q: Can we optimise GRAPH when the input is the Null Multiset to just return the Null Multiset?

            bool datasetOk = false;

            try
            {
                List <String> activeGraphs = new List <string>();

                // Get the URIs of Graphs that should be evaluated over
                if (_graphSpecifier.TokenType != Token.VARIABLE)
                {
                    switch (_graphSpecifier.TokenType)
                    {
                    case Token.URI:
                    case Token.QNAME:
                        Uri activeGraphUri = UriFactory.Create(Tools.ResolveUriOrQName(_graphSpecifier, context.Query.NamespaceMap, context.Query.BaseUri));
                        if (context.Data.HasGraph(activeGraphUri))
                        {
                            // If the Graph is explicitly specified and there are FROM/FROM NAMED present then the Graph
                            // URI must be in the graphs specified by a FROM/FROM NAMED or the result is null
                            if (context.Query == null ||
                                ((!context.Query.DefaultGraphs.Any() && !context.Query.NamedGraphs.Any()) ||
                                 context.Query.NamedGraphs.Any(u => EqualityHelper.AreUrisEqual(activeGraphUri, u)))
                                )
                            {
                                // Either there was no Query
                                // OR there were no Default/Named Graphs (hence any Graph URI is permitted)
                                // OR the specified URI was a Named Graph URI
                                // In any case we can go ahead and set the active Graph
                                activeGraphs.Add(activeGraphUri.AbsoluteUri);
                            }
                            else
                            {
                                // The specified URI was not present in the Named Graphs so return null
                                context.OutputMultiset = new NullMultiset();
                                return(context.OutputMultiset);
                            }
                        }
                        else
                        {
                            // If specifies a specific Graph and not in the Dataset result is a null multiset
                            context.OutputMultiset = new NullMultiset();
                            return(context.OutputMultiset);
                        }
                        break;

                    default:
                        throw new RdfQueryException("Cannot use a '" + _graphSpecifier.GetType().ToString() + "' Token to specify the Graph for a GRAPH clause");
                    }
                }
                else
                {
                    String gvar = _graphSpecifier.Value.Substring(1);

                    // Watch out for the case in which the Graph Variable is not bound for all Sets in which case
                    // we still need to operate over all Graphs
                    if (context.InputMultiset.ContainsVariable(gvar) && context.InputMultiset.Sets.All(s => s[gvar] != null))
                    {
                        // If there are already values bound to the Graph variable for all Input Solutions then we limit the Query to those Graphs
                        List <Uri> graphUris = new List <Uri>();
                        foreach (ISet s in context.InputMultiset.Sets)
                        {
                            INode temp = s[gvar];
                            if (temp == null)
                            {
                                continue;
                            }
                            if (temp.NodeType != NodeType.Uri)
                            {
                                continue;
                            }
                            activeGraphs.Add(temp.ToString());
                            graphUris.Add(((IUriNode)temp).Uri);
                        }
                    }
                    else
                    {
                        // Nothing yet bound to the Graph Variable so the Query is over all the named Graphs
                        if (context.Query != null && context.Query.NamedGraphs.Any())
                        {
                            // Query specifies one/more named Graphs
                            activeGraphs.AddRange(context.Query.NamedGraphs.Select(u => u.AbsoluteUri));
                        }
                        else if (context.Query != null && context.Query.DefaultGraphs.Any() && !context.Query.NamedGraphs.Any())
                        {
                            // Gives null since the query dataset does not include any named graphs
                            context.OutputMultiset = new NullMultiset();
                            return(context.OutputMultiset);
                        }
                        else
                        {
                            // Query is over entire dataset/default Graph since no named Graphs are explicitly specified
                            activeGraphs.AddRange(context.Data.GraphUris.Select(u => u.ToSafeString()));
                        }
                    }
                }

                // Remove all duplicates from Active Graphs to avoid duplicate results
                activeGraphs = activeGraphs.Distinct().ToList();

                // Evaluate the inner pattern
                BaseMultiset initialInput = context.InputMultiset;
                BaseMultiset finalResult  = new Multiset();

                // Evalute for each Graph URI and union the results
                foreach (String uri in activeGraphs)
                {
                    // Always use the same Input for each Graph URI and set that Graph to be the Active Graph
                    // Be sure to translate String.Empty back to the null URI to select the default graph
                    // correctly
                    context.InputMultiset = initialInput;
                    Uri currGraphUri = (uri.Equals(String.Empty)) ? null : UriFactory.Create(uri);

                    // Set Active Graph
                    if (currGraphUri == null)
                    {
                        // GRAPH operates over named graphs only so default graph gets skipped
                        continue;
                    }
                    // The result of the HasGraph() call is ignored we just make it so datasets with any kind of
                    // load on demand behaviour work properly
                    context.Data.HasGraph(currGraphUri);
                    // All we actually care about is setting the active graph
                    context.Data.SetActiveGraph(currGraphUri);
                    datasetOk = true;

                    // Evaluate for the current Active Graph
                    BaseMultiset result = context.Evaluate(_pattern);

                    // Merge the Results into our overall Results
                    if (result is NullMultiset)
                    {
                        // Don't do anything, adds nothing to the results
                    }
                    else if (result is IdentityMultiset)
                    {
                        // Adds a single row to the results
                        if (_graphSpecifier.TokenType == Token.VARIABLE)
                        {
                            // Include graph variable if not yet bound
                            INode currGraph = new UriNode(null, currGraphUri);
                            Set   s         = new Set();
                            s.Add(_graphSpecifier.Value.Substring(1), currGraph);
                            finalResult.Add(s);
                        }
                        else
                        {
                            finalResult.Add(new Set());
                        }
                    }
                    else
                    {
                        // If the Graph Specifier is a Variable then we must either bind the
                        // variable or eliminate solutions which have an incorrect value for it
                        if (_graphSpecifier.TokenType == Token.VARIABLE)
                        {
                            String gvar      = _graphSpecifier.Value.Substring(1);
                            INode  currGraph = new UriNode(null, currGraphUri);
                            foreach (int id in result.SetIDs.ToList())
                            {
                                ISet s = result[id];
                                if (s[gvar] == null)
                                {
                                    // If Graph Variable is not yet bound for solution bind it
                                    s.Add(gvar, currGraph);
                                }
                                else if (!s[gvar].Equals(currGraph))
                                {
                                    // If Graph Variable is bound for solution and doesn't match
                                    // current Graph then we have to remove the solution
                                    result.Remove(id);
                                }
                            }
                        }
                        // Union solutions into the Results
                        finalResult.Union(result);
                    }

                    // Reset the Active Graph after each pass
                    context.Data.ResetActiveGraph();
                    datasetOk = false;
                }

                // Return the final result
                if (finalResult.IsEmpty)
                {
                    finalResult = new NullMultiset();
                }
                context.OutputMultiset = finalResult;
            }
            finally
            {
                if (datasetOk)
                {
                    context.Data.ResetActiveGraph();
                }
            }

            return(context.OutputMultiset);
        }
Esempio n. 4
0
        public void SparqlMultisetLeftJoin()
        {
            //Create a load of Nodes to use in the tests
            Graph g = new Graph();
            g.NamespaceMap.AddNamespace(String.Empty, new Uri("http://example.org"));
            IUriNode s1 = g.CreateUriNode(":s1");
            IUriNode s2 = g.CreateUriNode(":s2");
            IUriNode p1 = g.CreateUriNode(":p1");
            IUriNode p2 = g.CreateUriNode(":p2");
            IUriNode rdfsLabel = g.CreateUriNode("rdfs:label");
            ILiteralNode o1 = g.CreateLiteralNode("Some Text");
            ILiteralNode o2 = g.CreateLiteralNode("1", new Uri(XmlSpecsHelper.XmlSchemaDataTypeInteger));

            //Create an ID and Null Multiset
            IdentityMultiset id = new IdentityMultiset();
            NullMultiset nullset = new NullMultiset();

            //Create and Populate a Multiset
            Multiset m = new Multiset();
            Set s = new Set();
            s.Add("s", s1);
            s.Add("p", p1);
            s.Add("o", o1);
            m.Add(s);
            s = new Set();
            s.Add("s", s2);
            s.Add("p", p2);
            s.Add("o", o2);
            m.Add(s);

            //Create and Populate another Multiset
            Multiset n = new Multiset();
            s = new Set();
            s.Add("s", s1);
            s.Add("label", o1);
            n.Add(s);

            //Create and Populate another Multiset
            Multiset d = new Multiset();
            s = new Set();
            s.Add("s1", s1);
            s.Add("p1", p1);
            s.Add("o1", o1);
            d.Add(s);
            s = new Set();
            s.Add("s1", s2);
            s.Add("p1", p2);
            s.Add("o1", o2);
            d.Add(s);

            //Show the Sets
            Console.WriteLine("LHS");
            foreach (Set set in m.Sets)
            {
                Console.WriteLine(set.ToString());
            }
            Console.WriteLine();
            Console.WriteLine("RHS");
            foreach (Set set in n.Sets)
            {
                Console.WriteLine(set.ToString());
            }
            Console.WriteLine();
            Console.WriteLine("D");
            foreach (Set set in d.Sets)
            {
                Console.WriteLine(set.ToString());
            }
            Console.WriteLine();

            //Try a Join to Identity
            Console.WriteLine("Join ID-LHS");
            BaseMultiset join = id.Join(m);
            foreach (Set set in join.Sets)
            {
                Console.WriteLine(set.ToString());
            }
            Console.WriteLine();

            //Try a Join to Identity
            Console.WriteLine("Join LHS-ID");
            join = m.Join(id);
            foreach (Set set in join.Sets)
            {
                Console.WriteLine(set.ToString());
            }
            Console.WriteLine();

            //Try a Join to Null
            Console.WriteLine("Join NULL-LHS");
            join = nullset.Join(m);
            foreach (Set set in join.Sets)
            {
                Console.WriteLine(set.ToString());
            }
            Console.WriteLine();

            //Try a Join to Null
            Console.WriteLine("Join LHS-NULL");
            join = m.Join(nullset);
            foreach (Set set in join.Sets)
            {
                Console.WriteLine(set.ToString());
            }
            Console.WriteLine();

            //Try a LeftJoin
            Console.WriteLine("LeftJoin NULL-LHS");
            BaseMultiset leftjoin = nullset.LeftJoin(m, new BooleanExpressionTerm(true));
            foreach (Set set in leftjoin.Sets)
            {
                Console.WriteLine(set.ToString());
            }
            Console.WriteLine();

            //Try a LeftJoin
            Console.WriteLine("LeftJoin LHS-NULL");
            leftjoin = m.LeftJoin(nullset, new BooleanExpressionTerm(true));
            foreach (Set set in leftjoin.Sets)
            {
                Console.WriteLine(set.ToString());
            }
            Console.WriteLine();

            //Try a Join
            Console.WriteLine("Join LHS-RHS");
            join = m.Join(n);
            foreach (Set set in join.Sets)
            {
                Console.WriteLine(set.ToString());
            }
            Console.WriteLine();
           
            //Try a LeftOuterJoin
            Console.WriteLine("LeftJoin LHS-RHS");
            leftjoin = m.LeftJoin(n, new BooleanExpressionTerm(true));
            foreach (Set set in leftjoin.Sets)
            {
                Console.WriteLine(set.ToString());
            }
            Console.WriteLine();

            //Try a Produce
            Console.WriteLine("Product LHS-RHS");
            BaseMultiset product = m.Product(n);
            foreach (Set set in product.Sets)
            {
                Console.WriteLine(set.ToString());
            }
            Console.WriteLine();

            //Try a Join to Self
            Console.WriteLine("Product LHS-D");
            product = m.Product(d);
            foreach (Set set in product.Sets)
            {
                Console.WriteLine(set.ToString());
            }
            Console.WriteLine();

            //Try a Union
            Console.WriteLine("Union LHS-RHS");
            BaseMultiset union = m.Union(n);
            foreach (Set set in union.Sets)
            {
                Console.WriteLine(set.ToString());
            }
            Console.WriteLine();
        }
Esempio n. 5
0
        /// <summary>
        /// Evaluates the BGP against the Evaluation Context.
        /// </summary>
        /// <param name="context">Evaluation Context.</param>
        /// <returns></returns>
        public override BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            bool         halt;
            BaseMultiset results      = null;
            int          origRequired = _requiredResults;

            // May need to detect the actual amount of required results if not specified at instantation
            if (_requiredResults < 0)
            {
                if (context.Query != null)
                {
                    if (context.Query.HasDistinctModifier || (context.Query.OrderBy != null && !context.Query.IsOptimisableOrderBy) || context.Query.GroupBy != null || context.Query.Having != null || context.Query.Bindings != null)
                    {
                        // If there's an DISTINCT/ORDER BY/GROUP BY/HAVING/BINDINGS present then can't do Lazy evaluation
                        _requiredResults = -1;
                    }
                    else
                    {
                        int limit  = context.Query.Limit;
                        int offset = context.Query.Offset;
                        if (limit >= 0 && offset >= 0)
                        {
                            // If there is a Limit and Offset specified then the required results is the LIMIT+OFFSET
                            _requiredResults = limit + offset;
                        }
                        else if (limit >= 0)
                        {
                            // If there is just a Limit specified then the required results is the LIMIT
                            _requiredResults = limit;
                        }
                        else
                        {
                            // In any other case required results is everything i.e. -1
                            _requiredResults = -1;
                        }
                    }
                    Debug.WriteLine("Lazy Evaluation - Number of required results is " + _requiredResults);
                }
            }

            switch (_requiredResults)
            {
            case -1:
                // If required results is everything just use normal evaluation as otherwise
                // lazy evaluation will significantly impact performance and lead to an apparent infinite loop
                return(base.Evaluate(context));

            case 0:
                // Don't need any results
                results = new NullMultiset();
                break;

            default:
                // Do streaming evaluation
                if (_requiredResults != 0)
                {
                    results = StreamingEvaluate(context, 0, out halt);
                    if (results is Multiset && results.IsEmpty)
                    {
                        results = new NullMultiset();
                    }
                }
                break;
            }
            _requiredResults = origRequired;

            context.OutputMultiset = results;
            context.OutputMultiset.Trim();
            return(context.OutputMultiset);
        }
Esempio n. 6
0
        /// <summary>
        /// Evaluates the BGP against the Evaluation Context
        /// </summary>
        /// <param name="context">Evaluation Context</param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            bool halt;
            BaseMultiset results = this.StreamingEvaluate(context, 0, out halt);
            if (results is Multiset && results.IsEmpty) results = new NullMultiset();

            context.OutputMultiset = results;
            context.OutputMultiset.Trim();
            return context.OutputMultiset;
        }
Esempio n. 7
0
        /// <summary>
        /// Evaluates the Graph Clause by setting up the dataset, applying the pattern and then generating additional bindings if necessary
        /// </summary>
        /// <param name="context">Evaluation Context</param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            BaseMultiset result;

            //Q: Can we optimise GRAPH when the input is the Null Multiset to just return the Null Multiset?

            if (this._pattern is Bgp && ((Bgp)this._pattern).IsEmpty)
            {
                //Optimise the case where we have GRAPH ?g {} by not setting the Graph and just returning
                //a Null Multiset
                result = new NullMultiset();
            }
            else
            {
                bool datasetOk = false;
                try
                {
                    List<String> activeGraphs = new List<string>();

                    //Get the URIs of Graphs that should be evaluated over
                    if (this._graphSpecifier.TokenType != Token.VARIABLE)
                    {
                        switch (this._graphSpecifier.TokenType)
                        {
                            case Token.URI:
                            case Token.QNAME:
                                Uri activeGraphUri = UriFactory.Create(Tools.ResolveUriOrQName(this._graphSpecifier, context.Query.NamespaceMap, context.Query.BaseUri));
                                if (context.Data.HasGraph(activeGraphUri))
                                {
                                    //If the Graph is explicitly specified and there are FROM NAMED present then the Graph
                                    //URI must be in the graphs specified by a FROM NAMED or the result is null
                                    if (context.Query == null || !context.Query.NamedGraphs.Any() || context.Query.NamedGraphs.Any(u => EqualityHelper.AreUrisEqual(activeGraphUri, u)))
                                    {
                                        //Either there was no Query
                                        //OR there were no Named Graphs (hence any Graph URI is permitted)
                                        //OR the specified URI was a Named Graph URI
                                        //In any case we can go ahead and set the active Graph
                                        activeGraphs.Add(activeGraphUri.ToString());
                                    }
                                    else
                                    {
                                        //The specified URI was not present in the Default/Named Graphs so return null
                                        context.OutputMultiset = new NullMultiset();
                                        return context.OutputMultiset;
                                    }
                                }
                                else
                                {
                                    //If specifies a specific Graph and not in the Dataset result is a null multiset
                                    context.OutputMultiset = new NullMultiset();
                                    return context.OutputMultiset;
                                }
                                break;
                            default:
                                throw new RdfQueryException("Cannot use a '" + this._graphSpecifier.GetType().ToString() + "' Token to specify the Graph for a GRAPH clause");
                        }
                    }
                    else
                    {
                        String gvar = this._graphSpecifier.Value.Substring(1);

                        //Watch out for the case in which the Graph Variable is not bound for all Sets in which case
                        //we still need to operate over all Graphs
                        if (context.InputMultiset.ContainsVariable(gvar) && context.InputMultiset.Sets.All(s => s[gvar] != null))
                        {
                            //If there are already values bound to the Graph variable for all Input Solutions then we limit the Query to those Graphs
                            List<Uri> graphUris = new List<Uri>();
                            foreach (ISet s in context.InputMultiset.Sets)
                            {
                                INode temp = s[gvar];
                                if (temp != null)
                                {
                                    if (temp.NodeType == NodeType.Uri)
                                    {
                                        activeGraphs.Add(temp.ToString());
                                        graphUris.Add(((IUriNode)temp).Uri);
                                    }
                                }
                            }
                        }
                        else
                        {
                            //Nothing yet bound to the Graph Variable so the Query is over all the named Graphs
                            if (context.Query != null && context.Query.NamedGraphs.Any())
                            {
                                //Query specifies one/more named Graphs
                                activeGraphs.AddRange(context.Query.NamedGraphs.Select(u => u.ToString()));
                            }
                            else
                            {
                                //Query is over entire dataset/default Graph since no named Graphs are explicitly specified
                                activeGraphs.AddRange(context.Data.GraphUris.Select(u => u.ToSafeString()));
                            }
                        }
                    }

                    //Remove all duplicates from Active Graphs to avoid duplicate results
                    activeGraphs = activeGraphs.Distinct().ToList();

                    //Evaluate the inner pattern
                    BaseMultiset initialInput = context.InputMultiset;
                    BaseMultiset finalResult = new Multiset();

                    //Evalute for each Graph URI and union the results
                    foreach (String uri in activeGraphs)
                    {
                        //Always use the same Input for each Graph URI and set that Graph to be the Active Graph
                        //Be sure to translate String.Empty back to the null URI to select the default graph
                        //correctly
                        context.InputMultiset = initialInput;
                        Uri currGraphUri = (uri.Equals(String.Empty)) ? null : UriFactory.Create(uri);

                        //Set Active Graph
                        if (currGraphUri == null)
                        {
                            //GRAPH operates over named graphs only so default graph gets skipped
                            continue;
                        }
                        else
                        {
                            //The result of the HasGraph() call is ignored we just make it so datasets with any kind of
                            //load on demand behaviour work properly
                            context.Data.HasGraph(currGraphUri);
                            //All we actually care about is setting the active graph
                            context.Data.SetActiveGraph(currGraphUri);
                        }
                        datasetOk = true;

                        //Evaluate for the current Active Graph
                        result = context.Evaluate(this._pattern);

                        //Merge the Results into our overall Results
                        if (result is NullMultiset || result is IdentityMultiset)
                        {
                            //Don't do anything
                        }
                        else
                        {
                            //If the Graph Specifier is a Variable then we must either bind the
                            //variable or eliminate solutions which have an incorrect value for it
                            if (this._graphSpecifier.TokenType == Token.VARIABLE)
                            {
                                String gvar = this._graphSpecifier.Value.Substring(1);
                                INode currGraph = (currGraphUri == null) ? null : new UriNode(null, currGraphUri);
                                foreach (int id in result.SetIDs.ToList())
                                {
                                    ISet s = result[id];
                                    if (s[gvar] == null)
                                    {
                                        //If Graph Variable is not yet bound for solution bind it
                                        s.Add(gvar, currGraph);
                                    }
                                    else if (!s[gvar].Equals(currGraph))
                                    {
                                        //If Graph Variable is bound for solution and doesn't match
                                        //current Graph then we have to remove the solution
                                        result.Remove(id);
                                    }
                                }
                            }
                            //Union solutions into the Results
                            finalResult.Union(result);
                        }

                        //Reset the Active Graph after each pass
                        context.Data.ResetActiveGraph();
                        datasetOk = false;
                    }

                    //Return the final result
                    if (finalResult.IsEmpty) finalResult = new NullMultiset();
                    context.OutputMultiset = finalResult;
                }
                finally
                {
                    if (datasetOk) context.Data.ResetActiveGraph();
                }
            }

            return context.OutputMultiset;
        }
Esempio n. 8
0
        /// <summary>
        /// Evaluates the Graph Clause by setting up the dataset, applying the pattern and then generating additional bindings if necessary
        /// </summary>
        /// <param name="context">Evaluation Context</param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            BaseMultiset result;

            //Q: Can we optimise GRAPH when the input is the Null Multiset to just return the Null Multiset?

            if (this._pattern is Bgp && ((Bgp)this._pattern).IsEmpty)
            {
                //Optimise the case where we have GRAPH ?g {} by not setting the Graph and just returning
                //a Null Multiset
                result = new NullMultiset();
            }
            else
            {
                bool datasetOk = false;
                try
                {
                    List <String> activeGraphs = new List <string>();

                    //Get the URIs of Graphs that should be evaluated over
                    if (this._graphSpecifier.TokenType != Token.VARIABLE)
                    {
                        switch (this._graphSpecifier.TokenType)
                        {
                        case Token.URI:
                        case Token.QNAME:
                            Uri activeGraphUri = new Uri(Tools.ResolveUriOrQName(this._graphSpecifier, context.Query.NamespaceMap, context.Query.BaseUri));
                            if (context.Data.HasGraph(activeGraphUri))
                            {
                                //If the Graph is explicitly specified and there are FROM NAMED present then the Graph
                                //URI must be in the graphs specified by a FROM NAMED or the result is null
                                if (context.Query != null &&
                                    ((!context.Query.DefaultGraphs.Any() && !context.Query.NamedGraphs.Any()) ||
                                     context.Query.DefaultGraphs.Any(u => EqualityHelper.AreUrisEqual(activeGraphUri, u)) ||
                                     context.Query.NamedGraphs.Any(u => EqualityHelper.AreUrisEqual(activeGraphUri, u)))
                                    )
                                {
                                    //Either there was no Query OR there were no Default/Named Graphs OR
                                    //the specified URI was either a Default/Named Graph URI
                                    //In any case we can go ahead and set the active Graph
                                    activeGraphs.Add(activeGraphUri.ToString());
                                }
                                else
                                {
                                    //The specified URI was not present in the Default/Named Graphs so return null
                                    context.OutputMultiset = new NullMultiset();
                                    return(context.OutputMultiset);
                                }
                            }
                            else
                            {
                                //If specifies a specific Graph and not in the Dataset result is a null multiset
                                context.OutputMultiset = new NullMultiset();
                                return(context.OutputMultiset);
                            }
                            break;

                        default:
                            throw new RdfQueryException("Cannot use a '" + this._graphSpecifier.GetType().ToString() + "' Token to specify the Graph for a GRAPH clause");
                        }
                    }
                    else
                    {
                        String gvar = this._graphSpecifier.Value.Substring(1);

                        //Watch out for the case in which the Graph Variable is not bound for all Sets in which case
                        //we still need to operate over all Graphs
                        if (context.InputMultiset.ContainsVariable(gvar) && context.InputMultiset.Sets.All(s => s[gvar] != null))
                        {
                            //If there are already values bound to the Graph variable for all Input Solutions then we limit the Query to those Graphs
                            List <Uri> graphUris = new List <Uri>();
                            foreach (ISet s in context.InputMultiset.Sets)
                            {
                                INode temp = s[gvar];
                                if (temp != null)
                                {
                                    if (temp.NodeType == NodeType.Uri)
                                    {
                                        activeGraphs.Add(temp.ToString());
                                        graphUris.Add(((IUriNode)temp).Uri);
                                    }
                                }
                            }
                        }
                        else
                        {
                            //Nothing yet bound to the Graph Variable so the Query is over all the named Graphs
                            if (context.Query != null && context.Query.NamedGraphs.Any())
                            {
                                //Query specifies one/more named Graphs
                                activeGraphs.AddRange(context.Query.NamedGraphs.Select(u => u.ToString()));
                            }
                            else
                            {
                                //Query is over entire dataset/default Graph since no named Graphs are explicitly specified
                                activeGraphs.AddRange(context.Data.GraphUris.Select(u => u.ToSafeString()));
                            }
                        }
                    }

                    //Remove all duplicates from Active Graphs to avoid duplicate results
                    activeGraphs = activeGraphs.Distinct().ToList();

                    //Evaluate the inner pattern
                    BaseMultiset initialInput = context.InputMultiset;
                    BaseMultiset finalResult  = new Multiset();

                    //Evalute for each Graph URI and union the results
                    foreach (String uri in activeGraphs)
                    {
                        //Always use the same Input for each Graph URI and set that Graph to be the Active Graph
                        //Be sure to translate String.Empty back to the null URI to select the default graph
                        //correctly
                        context.InputMultiset = initialInput;
                        Uri currGraphUri = (uri.Equals(String.Empty)) ? null : new Uri(uri);

                        //This bit of logic takes care of the fact that calling SetActiveGraph((Uri)null) resets the
                        //Active Graph to be the default graph which if the default graph is null is usually the Union of
                        //all Graphs in the Store
                        if (currGraphUri == null && context.Data.DefaultGraph == null && context.Data.UsesUnionDefaultGraph)
                        {
                            if (context.Data.HasGraph(null))
                            {
                                context.Data.SetActiveGraph(context.Data[null]);
                            }
                            else
                            {
                                continue;
                            }
                        }
                        else
                        {
                            context.Data.SetActiveGraph(currGraphUri);
                        }
                        datasetOk = true;

                        //Evaluate for the current Active Graph
                        result = context.Evaluate(this._pattern);

                        //Merge the Results into our overall Results
                        if (result is NullMultiset || result is IdentityMultiset)
                        {
                            //Don't do anything
                        }
                        else
                        {
                            //If the Graph Specifier is a Variable then we must either bind the
                            //variable or eliminate solutions which have an incorrect value for it
                            if (this._graphSpecifier.TokenType == Token.VARIABLE)
                            {
                                String gvar      = this._graphSpecifier.Value.Substring(1);
                                INode  currGraph = (currGraphUri == null) ? null : new UriNode(null, currGraphUri);
                                foreach (int id in result.SetIDs.ToList())
                                {
                                    ISet s = result[id];
                                    if (s[gvar] == null)
                                    {
                                        //If Graph Variable is not yet bound for solution bind it
                                        s.Add(gvar, currGraph);
                                    }
                                    else if (!s[gvar].Equals(currGraph))
                                    {
                                        //If Graph Variable is bound for solution and doesn't match
                                        //current Graph then we have to remove the solution
                                        result.Remove(id);
                                    }
                                }
                            }
                            //Union solutions into the Results
                            finalResult.Union(result);
                        }

                        //Reset the Active Graph after each pass
                        context.Data.ResetActiveGraph();
                        datasetOk = false;
                    }

                    //Return the final result
                    if (finalResult.IsEmpty)
                    {
                        finalResult = new NullMultiset();
                    }
                    context.OutputMultiset = finalResult;
                }
                finally
                {
                    if (datasetOk)
                    {
                        context.Data.ResetActiveGraph();
                    }
                }
            }

            return(context.OutputMultiset);
        }
Esempio n. 9
0
        /// <summary>
        /// Evaluates the BGP against the Evaluation Context
        /// </summary>
        /// <param name="context">Evaluation Context</param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            bool halt;
            BaseMultiset results;
            int origRequired = this._requiredResults;

            //May need to detect the actual
            if (this._requiredResults < 0)
            {
                if (context.Query != null)
                {
                    if (context.Query.HasDistinctModifier || (context.Query.OrderBy != null && !context.Query.IsOptimisableOrderBy) || context.Query.GroupBy != null || context.Query.Having != null || context.Query.Bindings != null)
                    {
                        //If there's an DISTINCT/ORDER BY/GROUP BY/HAVING/BINDINGS present then can't do Lazy evaluation
                        this._requiredResults = -1;
                    }
                    else
                    {
                        int limit = context.Query.Limit;
                        int offset = context.Query.Offset;
                        if (limit >= 0 && offset >= 0)
                        {
                            //If there is a Limit and Offset specified then the required results is the LIMIT+OFFSET
                            this._requiredResults = limit + offset;
                        }
                        else if (limit >= 0)
                        {
                            //If there is just a Limit specified then the required results is the LIMIT
                            this._requiredResults = limit;
                        }
                        else
                        {
                            //In any other case required results is everything i.e. -1
                            this._requiredResults = -1;
                        }
                    }
                }
            }

            if (this._requiredResults != 0)
            {
                results = this.StreamingEvaluate(context, 0, out halt);
                if (results is Multiset && results.IsEmpty) results = new NullMultiset();
            }
            else
            {
                results = new NullMultiset();
            }
            this._requiredResults = origRequired;

            context.OutputMultiset = results;
            context.OutputMultiset.Trim();
            return context.OutputMultiset;
        }