Exemplo n.º 1
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);
        }
Exemplo n.º 2
0
 /// <summary>
 /// Gets whether the given URI represents the default graph of the dataset
 /// </summary>
 /// <param name="graphUri">Graph URI</param>
 /// <returns></returns>
 protected bool IsDefaultGraph(Uri graphUri)
 {
     return(EqualityHelper.AreUrisEqual(graphUri, this._defaultGraphUri));
 }
Exemplo 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)
        {
            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);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Evaluates the Command in the given Context
        /// </summary>
        /// <param name="context">Evaluation Context</param>
        public override void Evaluate(SparqlUpdateEvaluationContext context)
        {
            try
            {
                //If Source and Destination are same this is a no-op
                if (EqualityHelper.AreUrisEqual(this._sourceUri, this._destUri))
                {
                    return;
                }

                if (context.Data.HasGraph(this._sourceUri))
                {
                    //Get the Source Graph
                    IGraph source = context.Data.GetModifiableGraph(this._sourceUri);

                    //Create/Delete/Clear the Destination Graph
                    IGraph dest;
                    if (context.Data.HasGraph(this._destUri))
                    {
                        if (this._destUri == null)
                        {
                            dest = context.Data.GetModifiableGraph(this._destUri);
                            dest.Clear();
                        }
                        else
                        {
                            context.Data.RemoveGraph(this._destUri);
                            dest         = new Graph();
                            dest.BaseUri = this._destUri;
                            context.Data.AddGraph(dest);
                            dest = context.Data.GetModifiableGraph(this._destUri);
                        }
                    }
                    else
                    {
                        dest         = new Graph();
                        dest.BaseUri = this._destUri;
                        context.Data.AddGraph(dest);
                    }

                    //Move data from the Source into the Destination
                    dest.Merge(source);

                    //Delete/Clear the Source Graph
                    if (this._sourceUri == null)
                    {
                        source.Clear();
                    }
                    else
                    {
                        context.Data.RemoveGraph(this._sourceUri);
                    }
                }
                else
                {
                    //Only show error if not Silent
                    if (!this._silent)
                    {
                        if (this._sourceUri != null)
                        {
                            throw new SparqlUpdateException("Cannot MOVE from Graph <" + this._sourceUri.AbsoluteUri + "> as it does not exist");
                        }
                        else
                        {
                            //This would imply a more fundamental issue with the Dataset not understanding that null means default graph
                            throw new SparqlUpdateException("Cannot MOVE from the Default Graph as it does not exist");
                        }
                    }
                }
            }
            catch
            {
                //If not silent throw the exception upwards
                if (!this._silent)
                {
                    throw;
                }
            }
        }
        /// <summary>
        /// Constructs a Full Text Match property function.
        /// </summary>
        /// <param name="info">Property Function information.</param>
        public FullTextMatchPropertyFunction(PropertyFunctionInfo info)
        {
            if (info == null)
            {
                throw new ArgumentNullException("info");
            }
            if (!EqualityHelper.AreUrisEqual(info.FunctionUri, this.FunctionUri))
            {
                throw new ArgumentException("Property Function information is not valid for this function");
            }

            //Get basic arguments
            this._matchVar = info.SubjectArgs[0];
            if (this._matchVar.VariableName != null)
            {
                this._vars.Add(this._matchVar.VariableName);
            }
            if (info.SubjectArgs.Count == 2)
            {
                this._scoreVar = info.SubjectArgs[1];
                if (this._scoreVar.VariableName != null)
                {
                    this._vars.Add(this._scoreVar.VariableName);
                }
            }

            //Check extended arguments
            this._searchVar = info.ObjectArgs[0];
            if (this._searchVar.VariableName != null)
            {
                this._vars.Add(this._searchVar.VariableName);
            }
            switch (info.ObjectArgs.Count)
            {
            case 1:
                break;

            case 2:
                PatternItem arg = info.ObjectArgs[1];
                if (arg.VariableName != null)
                {
                    throw new RdfQueryException("Cannot use a variable as the limit/score threshold for full text queries, must use a numeric constant");
                }
                IValuedNode n = ((NodeMatchPattern)arg).Node.AsValuedNode();
                switch (n.NumericType)
                {
                case SparqlNumericType.Integer:
                    this._limit = (int)n.AsInteger();
                    break;

                case SparqlNumericType.Decimal:
                case SparqlNumericType.Double:
                case SparqlNumericType.Float:
                    this._threshold = n.AsDouble();
                    break;

                default:
                    throw new RdfQueryException("Cannot use a non-numeric constant as the limit/score threshold for full text queries, must use a numeric constant");
                }
                break;

            case 3:
            default:
                PatternItem arg1 = info.ObjectArgs[1];
                PatternItem arg2 = info.ObjectArgs[2];
                if (arg1.VariableName != null || arg2.VariableName != null)
                {
                    throw new RdfQueryException("Cannot use a variable as the limit/score threshold for full text queries, must use a numeric constant");
                }
                IValuedNode n1 = ((NodeMatchPattern)arg1).Node.AsValuedNode();
                switch (n1.NumericType)
                {
                case SparqlNumericType.NaN:
                    throw new RdfQueryException("Cannot use a non-numeric constant as the score threshold for full text queries, must use a numeric constant");

                default:
                    this._threshold = n1.AsDouble();
                    break;
                }
                IValuedNode n2 = ((NodeMatchPattern)arg2).Node.AsValuedNode();
                switch (n2.NumericType)
                {
                case SparqlNumericType.NaN:
                    throw new RdfQueryException("Cannot use a non-numeric constant as the limit for full text queries, must use a numeric constant");

                default:
                    this._limit = (int)n2.AsInteger();
                    break;
                }
                break;
            }
        }