Example #1
0
        /// <summary>
        /// Evaluates the LeftJoin
        /// </summary>
        /// <param name="context">Evaluation Context</param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            // Need to be careful about whether we linearize (CORE-406)
            if (!CanLinearizeLhs(context))
            {
                context.InputMultiset = new IdentityMultiset();
            }
            BaseMultiset lhsResult = context.Evaluate(_lhs);

            context.CheckTimeout();

            if (lhsResult is NullMultiset)
            {
                context.OutputMultiset = lhsResult;
            }
            else if (lhsResult.IsEmpty)
            {
                context.OutputMultiset = new NullMultiset();
            }
            else
            {
                // Only execute the RHS if the LHS had some results
                // Need to be careful about whether we linearize (CORE-406)
                context.InputMultiset = CanFlowResultsToRhs(context) && !IsCrossProduct ? lhsResult : new IdentityMultiset();
                BaseMultiset rhsResult = context.Evaluate(_rhs);
                context.CheckTimeout();

                context.OutputMultiset = lhsResult.LeftJoin(rhsResult, _filter.Expression);
                context.CheckTimeout();
            }

            context.InputMultiset = context.OutputMultiset;
            return(context.OutputMultiset);
        }
Example #2
0
        /// <summary>
        /// Evaluates an ExistsJoin
        /// </summary>
        /// <param name="context">Evaluation Context</param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            BaseMultiset initialInput = context.InputMultiset;
            BaseMultiset lhsResult    = context.Evaluate(_lhs);//this._lhs.Evaluate(context);

            context.CheckTimeout();

            if (lhsResult is NullMultiset)
            {
                context.OutputMultiset = lhsResult;
            }
            else if (lhsResult.IsEmpty)
            {
                context.OutputMultiset = new NullMultiset();
            }
            else
            {
                // Only execute the RHS if the LHS had results
                context.InputMultiset = lhsResult;
                BaseMultiset rhsResult = context.Evaluate(_rhs);//this._rhs.Evaluate(context);
                context.CheckTimeout();

                context.OutputMultiset = lhsResult.ExistsJoin(rhsResult, _mustExist);
                context.CheckTimeout();
            }

            context.InputMultiset = context.OutputMultiset;
            return(context.OutputMultiset);
        }
Example #3
0
        /// <summary>
        /// Evaluates the Union
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            BaseMultiset initialInput = context.InputMultiset;

            if (_lhs is Extend || _rhs is Extend)
            {
                initialInput = new IdentityMultiset();
            }

            context.InputMultiset = initialInput;
            BaseMultiset lhsResult = context.Evaluate(_lhs);

            context.CheckTimeout();

            context.InputMultiset = initialInput;
            BaseMultiset rhsResult = context.Evaluate(_rhs);

            context.CheckTimeout();

            context.OutputMultiset = lhsResult.Union(rhsResult);
            context.CheckTimeout();

            context.InputMultiset = context.OutputMultiset;
            return(context.OutputMultiset);
        }
Example #4
0
        /// <summary>
        /// Evaluates the Lazy Union
        /// </summary>
        /// <param name="context">Evaluation Context</param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            BaseMultiset initialInput = context.InputMultiset;
            BaseMultiset lhsResult    = context.Evaluate(this._lhs);//this._lhs.Evaluate(context);

            context.CheckTimeout();

            if (lhsResult.Count >= this._requiredResults || this._requiredResults == -1)
            {
                //Only evaluate the RHS if the LHS didn't yield sufficient results
                context.InputMultiset = initialInput;
                BaseMultiset rhsResult = context.Evaluate(this._rhs);//this._rhs.Evaluate(context);
                context.CheckTimeout();

                context.OutputMultiset = lhsResult.Union(rhsResult);
                context.CheckTimeout();

                context.InputMultiset = context.OutputMultiset;
            }
            else
            {
                context.OutputMultiset = lhsResult;
            }
            return(context.OutputMultiset);
        }
Example #5
0
        /// <summary>
        /// Evaluates the Ask Union
        /// </summary>
        /// <param name="context">Evaluation Context</param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            BaseMultiset initialInput = context.InputMultiset;

            if (this._lhs is Extend || this._rhs is Extend)
            {
                initialInput = new IdentityMultiset();
            }

            context.InputMultiset = initialInput;
            BaseMultiset lhsResult = context.Evaluate(this._lhs);//this._lhs.Evaluate(context);

            context.CheckTimeout();

            if (lhsResult.IsEmpty)
            {
                //Only evaluate the RHS if the LHS was empty
                context.InputMultiset = initialInput;
                BaseMultiset rhsResult = context.Evaluate(this._rhs);//this._rhs.Evaluate(context);
                context.CheckTimeout();

                context.OutputMultiset = lhsResult.Union(rhsResult);
                context.CheckTimeout();

                context.InputMultiset = context.OutputMultiset;
            }
            else
            {
                context.OutputMultiset = lhsResult;
            }
            return(context.OutputMultiset);
        }
        /// <summary>
        /// Evaluates the Union
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            //Create a copy of the evaluation context for the RHS
            SparqlEvaluationContext context2 = new SparqlEvaluationContext(context.Query, context.Data, context.Processor);

            if (!(context.InputMultiset is IdentityMultiset))
            {
                context2.InputMultiset = new Multiset();
                foreach (ISet s in context.InputMultiset.Sets)
                {
                    context2.InputMultiset.Add(s.Copy());
                }
            }

            List <Uri> activeGraphs  = context.Data.ActiveGraphUris.ToList();
            List <Uri> defaultGraphs = context.Data.DefaultGraphUris.ToList();

            ParallelEvaluateDelegate d   = new ParallelEvaluateDelegate(this.ParallelEvaluate);
            IAsyncResult             lhs = d.BeginInvoke(this._lhs, context, activeGraphs, defaultGraphs, null, null);
            IAsyncResult             rhs = d.BeginInvoke(this._rhs, context2, activeGraphs, defaultGraphs, null, null);

            WaitHandle.WaitAll(new WaitHandle[] { lhs.AsyncWaitHandle, rhs.AsyncWaitHandle });

            bool rhsOk = false;

            try
            {
                BaseMultiset lhsResult = d.EndInvoke(lhs);
                rhsOk = true;
                BaseMultiset rhsResult = d.EndInvoke(rhs);
                context.CheckTimeout();

                context.OutputMultiset = lhsResult.Union(rhsResult);
                context.CheckTimeout();

                context.InputMultiset = context.OutputMultiset;
                return(context.OutputMultiset);
            }
            catch
            {
                if (!rhsOk)
                {
                    //Clean up the RHS evaluation call if the LHS has errored
                    try
                    {
                        d.EndInvoke(rhs);
                    }
                    catch
                    {
                        //Ignore this error as we're already going to throw the other error
                    }
                }
                throw;
            }
        }
        private void EvalFilteredProduct(SparqlEvaluationContext context, ISet x, BaseMultiset other, PartitionedMultiset partitionedSet)
        {
            int id = partitionedSet.GetNextBaseID();

            foreach (ISet y in other.Sets)
            {
                id++;
                ISet z = x.Join(y);
                z.ID = id;
                partitionedSet.Add(z);
                try
                {
                    if (!this._expr.Evaluate(context, z.ID).AsSafeBoolean())
                    {
                        //Means the expression evaluates to false so we discard the solution
                        partitionedSet.Remove(z.ID);
                    }
                }
                catch
                {
                    //Means the solution does not meet the FILTER and can be discarded
                    partitionedSet.Remove(z.ID);
                }
            }
            //Remember to check for timeouts occassionally
            context.CheckTimeout();
        }
Example #8
0
        /// <summary>
        /// Evaluates an ExistsJoin
        /// </summary>
        /// <param name="context">Evaluation Context</param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            BaseMultiset initialInput = context.InputMultiset;
            BaseMultiset lhsResult = context.Evaluate(this._lhs);//this._lhs.Evaluate(context);
            context.CheckTimeout();

            if (lhsResult is NullMultiset)
            {
                context.OutputMultiset = lhsResult;
            }
            else if (lhsResult.IsEmpty)
            {
                context.OutputMultiset = new NullMultiset();
            }
            else
            {
                //Only execute the RHS if the LHS had results
                context.InputMultiset = lhsResult;
                BaseMultiset rhsResult = context.Evaluate(this._rhs);//this._rhs.Evaluate(context);
                context.CheckTimeout();

                context.OutputMultiset = lhsResult.ExistsJoin(rhsResult, this._mustExist);
                context.CheckTimeout();
            }

            context.InputMultiset = context.OutputMultiset;
            return context.OutputMultiset;
        }
Example #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;

            context.CheckTimeout();
            BaseMultiset results = this.StreamingEvaluate(context, 0, out halt);

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

            context.OutputMultiset = results;
            context.OutputMultiset.Trim();
            return(context.OutputMultiset);
        }
Example #10
0
        /// <summary>
        /// Evaluates the Union
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            BaseMultiset initialInput = context.InputMultiset;
            BaseMultiset lhsResult    = context.Evaluate(this._lhs);//this._lhs.Evaluate(context);

            context.CheckTimeout();

            context.InputMultiset = initialInput;
            BaseMultiset rhsResult = context.Evaluate(this._rhs);//this._rhs.Evaluate(context);

            context.CheckTimeout();

            context.OutputMultiset = lhsResult.Union(rhsResult);
            context.CheckTimeout();

            context.InputMultiset = context.OutputMultiset;
            return(context.OutputMultiset);
        }
Example #11
0
        /// <summary>
        /// Evaluates the Union.
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            // Create a copy of the evaluation context for the RHS
            var context2 = new SparqlEvaluationContext(context.Query, context.Data, context.Processor);

            if (!(context.InputMultiset is IdentityMultiset))
            {
                context2.InputMultiset = new Multiset();
                foreach (var s in context.InputMultiset.Sets)
                {
                    context2.InputMultiset.Add(s.Copy());
                }
            }

            var activeGraphs  = context.Data.ActiveGraphUris.ToList();
            var defaultGraphs = context.Data.DefaultGraphUris.ToList();

            var lhsTask = Task.Factory.StartNew(() => ParallelEvaluate(Lhs, context, activeGraphs, defaultGraphs));
            var rhsTask = Task.Factory.StartNew(() => ParallelEvaluate(Rhs, context2, activeGraphs, defaultGraphs));

            Task[] evaluationTasks = { lhsTask, rhsTask };
            try
            {
                Task.WaitAll(evaluationTasks);
                context.CheckTimeout();
                var lhsResult = lhsTask.Result;
                var rhsResult = rhsTask.Result;
                context.OutputMultiset = lhsResult.Union(rhsResult);
                context.CheckTimeout();
                context.InputMultiset = context.OutputMultiset;
                return(context.OutputMultiset);
            }
            catch (AggregateException ex)
            {
                if (ex.InnerExceptions.Any())
                {
                    throw ex.InnerExceptions.First();
                }

                throw;
            }
        }
Example #12
0
        /// <summary>
        /// Evaluates the Minus join by evaluating the LHS and RHS and substracting the RHS results from the LHS.
        /// </summary>
        /// <param name="context">Evaluation Context.</param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            BaseMultiset initialInput = context.InputMultiset;
            BaseMultiset lhsResult    = context.Evaluate(_lhs);//this._lhs.Evaluate(context);

            context.CheckTimeout();

            if (lhsResult is NullMultiset)
            {
                context.OutputMultiset = lhsResult;
            }
            else if (lhsResult.IsEmpty)
            {
                context.OutputMultiset = new NullMultiset();
            }
            else if (_lhs.Variables.IsDisjoint(_rhs.Variables))
            {
                // If the RHS is disjoint then there is no need to evaluate the RHS
                context.OutputMultiset = lhsResult;
            }
            else
            {
                // If we get here then the RHS is not disjoint so it does affect the ouput

                // Only execute the RHS if the LHS had results
                // context.InputMultiset = lhsResult;
                context.InputMultiset = initialInput;
                BaseMultiset rhsResult = context.Evaluate(_rhs);//this._rhs.Evaluate(context);
                context.CheckTimeout();

                context.OutputMultiset = lhsResult.MinusJoin(rhsResult);
                context.CheckTimeout();
            }

            context.InputMultiset = context.OutputMultiset;
            return(context.OutputMultiset);
        }
Example #13
0
        /// <summary>
        /// Evaluates the Service Clause by generating instance(s) of <see cref="SparqlRemoteEndpoint">SparqlRemoteEndpoint</see> as required and issuing the query to the remote endpoint(s).
        /// </summary>
        /// <param name="context">Evaluation Context.</param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            SparqlRemoteEndpoint endpoint = GetRemoteEndpoint(context);

            try
            {
                context.OutputMultiset = new Multiset();
                foreach (var query in GetRemoteQueries(context, GetBindings(context)))
                {
                    // Try and get a Result Set from the Service
                    SparqlResultSet results = endpoint.QueryWithResultSet(query.ToString());
                    context.CheckTimeout();

                    // Transform this Result Set back into a Multiset
                    foreach (SparqlResult r in results)
                    {
                        context.OutputMultiset.Add(new Set(r));
                    }
                }
                return(context.OutputMultiset);
            }
            catch (Exception ex)
            {
                if (_silent)
                {
                    // If Evaluation Errors are SILENT is specified then a Multiset containing a single set with all values unbound is returned
                    // Unless some of the SPARQL queries did return results in which we just return the results we did obtain
                    if (context.OutputMultiset.IsEmpty)
                    {
                        Set s = new Set();
                        foreach (String var in _pattern.Variables.Distinct())
                        {
                            s.Add(var, null);
                        }
                        context.OutputMultiset.Add(s);
                    }
                    return(context.OutputMultiset);
                }
                else
                {
                    throw new RdfQueryException("Query execution failed because evaluating a SERVICE clause failed - this may be due to an error with the remote service", ex);
                }
            }
        }
Example #14
0
        /// <summary>
        /// Evaluates the Minus join by evaluating the LHS and RHS and substracting the RHS results from the LHS
        /// </summary>
        /// <param name="context">Evaluation Context</param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            BaseMultiset initialInput = context.InputMultiset;
            BaseMultiset lhsResult = context.Evaluate(this._lhs);//this._lhs.Evaluate(context);
            context.CheckTimeout();

            if (lhsResult is NullMultiset)
            {
                context.OutputMultiset = lhsResult;
            }
            else if (lhsResult.IsEmpty)
            {
                context.OutputMultiset = new NullMultiset();
            }
            else if (this._lhs.Variables.IsDisjoint(this._rhs.Variables))
            {
                //If the RHS is disjoint then there is no need to evaluate the RHS
                context.OutputMultiset = lhsResult;
            }
            else
            {
                //If we get here then the RHS is not disjoint so it does affect the ouput

                //Only execute the RHS if the LHS had results
                //context.InputMultiset = lhsResult;
                context.InputMultiset = initialInput;
                BaseMultiset rhsResult = context.Evaluate(this._rhs);//this._rhs.Evaluate(context);
                context.CheckTimeout();

                context.OutputMultiset = lhsResult.MinusJoin(rhsResult);
                context.CheckTimeout();
            }

            context.InputMultiset = context.OutputMultiset;
            return context.OutputMultiset;
        }
Example #15
0
        private BaseMultiset StreamingEvaluate(SparqlEvaluationContext context, int pattern, out bool halt)
        {
            halt = false;

            //Handle Empty BGPs
            if (pattern == 0 && this._triplePatterns.Count == 0)
            {
                context.OutputMultiset = new IdentityMultiset();
                return(context.OutputMultiset);
            }

            BaseMultiset initialInput, localOutput, results = null;

            //Determine whether the Pattern modifies the existing Input rather than joining to it
            bool modifies = (this._triplePatterns[pattern] is FilterPattern);
            bool extended = (pattern > 0 && this._triplePatterns[pattern - 1] is BindPattern);
            bool modified = (pattern > 0 && this._triplePatterns[pattern - 1] is FilterPattern);

            //Set up the Input and Output Multiset appropriately
            switch (pattern)
            {
            case 0:
                //Input is as given and Output is new empty multiset
                if (!modifies)
                {
                    initialInput = context.InputMultiset;
                }
                else
                {
                    //If the Pattern will modify the Input and is the first thing in the BGP then it actually modifies a new empty input
                    //This takes care of FILTERs being out of scope
                    initialInput = new Multiset();
                }
                localOutput = new Multiset();
                break;

            case 1:
                //Input becomes current Output and Output is new empty multiset
                initialInput = context.OutputMultiset;
                localOutput  = new Multiset();
                break;

            default:
                if (!extended && !modified)
                {
                    //Input is join of previous input and output and Output is new empty multiset
                    if (context.InputMultiset.IsDisjointWith(context.OutputMultiset))
                    {
                        //Disjoint so do a Product
                        initialInput = context.InputMultiset.ProductWithTimeout(context.OutputMultiset, context.RemainingTimeout);
                    }
                    else
                    {
                        //Normal Join
                        initialInput = context.InputMultiset.Join(context.OutputMultiset);
                    }
                }
                else
                {
                    initialInput = context.OutputMultiset;
                }
                localOutput = new Multiset();
                break;
            }
            context.InputMultiset  = initialInput;
            context.OutputMultiset = localOutput;

            //Get the Triple Pattern we're evaluating
            ITriplePattern temp         = this._triplePatterns[pattern];
            int            resultsFound = 0;
            int            prevResults  = -1;

            if (temp is TriplePattern)
            {
                //Find the first Triple which matches the Pattern
                TriplePattern        tp = (TriplePattern)temp;
                IEnumerable <Triple> ts = tp.GetTriples(context);

                //In the case that we're lazily evaluating an optimisable ORDER BY then
                //we need to apply OrderBy()'s to our enumeration
                //This only applies to the 1st pattern
                if (pattern == 0)
                {
                    if (context.Query != null)
                    {
                        if (context.Query.OrderBy != null && context.Query.IsOptimisableOrderBy)
                        {
                            IComparer <Triple> comparer = context.Query.OrderBy.GetComparer(tp);
                            if (comparer != null)
                            {
                                ts = ts.OrderBy(t => t, comparer);
                            }
                            else
                            {
                                //Can't get a comparer so can't optimise
                                this._requiredResults = -1;
                            }
                        }
                    }
                }

                foreach (Triple t in ts)
                {
                    //Remember to check for Timeouts during Lazy Evaluation
                    context.CheckTimeout();

                    if (tp.Accepts(context, t))
                    {
                        resultsFound++;
                        if (tp.IndexType == TripleIndexType.NoVariables)
                        {
                            localOutput            = new IdentityMultiset();
                            context.OutputMultiset = localOutput;
                        }
                        else
                        {
                            context.OutputMultiset.Add(tp.CreateResult(t));
                        }

                        //Recurse unless we're the last pattern
                        if (pattern < this._triplePatterns.Count - 1)
                        {
                            results = this.StreamingEvaluate(context, pattern + 1, out halt);

                            //If recursion leads to a halt then we halt and return immediately
                            if (halt && results.Count >= this._requiredResults && this._requiredResults != -1)
                            {
                                return(results);
                            }
                            else if (halt)
                            {
                                if (results.Count == 0)
                                {
                                    //If recursing leads to no results then eliminate all outputs
                                    //Also reset to prevResults to -1
                                    resultsFound = 0;
                                    localOutput  = new Multiset();
                                    prevResults  = -1;
                                }
                                else if (prevResults > -1)
                                {
                                    if (results.Count == prevResults)
                                    {
                                        //If the amount of results found hasn't increased then this match does not
                                        //generate any further solutions further down the recursion so we can eliminate
                                        //this from the results
                                        localOutput.Remove(localOutput.SetIDs.Max());
                                    }
                                }
                                prevResults = results.Count;

                                //If we're supposed to halt but not reached the number of required results then continue
                                context.InputMultiset  = initialInput;
                                context.OutputMultiset = localOutput;
                            }
                            else
                            {
                                //Otherwise we need to keep going here
                                //So must reset our input and outputs before continuing
                                context.InputMultiset  = initialInput;
                                context.OutputMultiset = new Multiset();
                                resultsFound--;
                            }
                        }
                        else
                        {
                            //If we're at the last pattern and we've found a match then we can halt
                            halt = true;

                            //Generate the final output and return it
                            if (context.InputMultiset.IsDisjointWith(context.OutputMultiset))
                            {
                                //Disjoint so do a Product
                                results = context.InputMultiset.ProductWithTimeout(context.OutputMultiset, context.RemainingTimeout);
                            }
                            else
                            {
                                //Normal Join
                                results = context.InputMultiset.Join(context.OutputMultiset);
                            }

                            //If not reached required number of results continue
                            if (results.Count >= this._requiredResults && this._requiredResults != -1)
                            {
                                context.OutputMultiset = results;
                                return(context.OutputMultiset);
                            }
                        }
                    }
                }
            }
            else if (temp is FilterPattern)
            {
                FilterPattern     filter     = (FilterPattern)temp;
                ISparqlExpression filterExpr = filter.Filter.Expression;

                if (filter.Variables.IsDisjoint(context.InputMultiset.Variables))
                {
                    //Remember to check for Timeouts during Lazy Evaluation
                    context.CheckTimeout();

                    //Filter is Disjoint so determine whether it has any affect or not
                    if (filter.Variables.Any())
                    {
                        //Has Variables but disjoint from input => not in scope so gets ignored

                        //Do we recurse or not?
                        if (pattern < this._triplePatterns.Count - 1)
                        {
                            //Recurse and return
                            results = this.StreamingEvaluate(context, pattern + 1, out halt);
                            return(results);
                        }
                        else
                        {
                            //We don't affect the input in any way so just return it
                            return(context.InputMultiset);
                        }
                    }
                    else
                    {
                        //No Variables so have to evaluate it to see if it gives true otherwise
                        try
                        {
                            if (filterExpr.EffectiveBooleanValue(context, 0))
                            {
                                if (pattern < this._triplePatterns.Count - 1)
                                {
                                    //Recurse and return
                                    results = this.StreamingEvaluate(context, pattern + 1, out halt);
                                    return(results);
                                }
                                else
                                {
                                    //Last Pattern and we evaluate to true so can return the input as-is
                                    halt = true;
                                    return(context.InputMultiset);
                                }
                            }
                        }
                        catch (RdfQueryException)
                        {
                            //Evaluates to false so eliminates all solutions (use an empty Multiset)
                            return(new Multiset());
                        }
                    }
                }
                else
                {
                    //Remember to check for Timeouts during Lazy Evaluation
                    context.CheckTimeout();

                    //Test each solution found so far against the Filter and eliminate those that evalute to false/error
                    foreach (int id in context.InputMultiset.SetIDs.ToList())
                    {
                        try
                        {
                            if (filterExpr.EffectiveBooleanValue(context, id))
                            {
                                //If evaluates to true then add to output
                                context.OutputMultiset.Add(context.InputMultiset[id]);
                            }
                        }
                        catch (RdfQueryException)
                        {
                            //Error means we ignore the solution
                        }
                    }

                    //Remember to check for Timeouts during Lazy Evaluation
                    context.CheckTimeout();

                    //Decide whether to recurse or not
                    resultsFound = context.OutputMultiset.Count;
                    if (pattern < this._triplePatterns.Count - 1)
                    {
                        //Recurse then return
                        //We can never decide whether to recurse again at this point as we are not capable of deciding
                        //which solutions should be dumped (that is the job of an earlier pattern in the BGP)
                        results = this.StreamingEvaluate(context, pattern + 1, out halt);

                        return(results);
                    }
                    else
                    {
                        halt = true;

                        //However many results we need we'll halt - previous patterns can call us again if they find more potential solutions
                        //for us to filter
                        return(context.OutputMultiset);
                    }
                }
            }
            else if (temp is BindPattern)
            {
                BindPattern       bind     = (BindPattern)temp;
                ISparqlExpression bindExpr = bind.AssignExpression;
                String            bindVar  = bind.VariableName;

                if (context.InputMultiset.ContainsVariable(bindVar))
                {
                    throw new RdfQueryException("Cannot use a BIND assigment to BIND to a variable that has previously been used in the Query");
                }
                else
                {
                    //Remember to check for Timeouts during Lazy Evaluation
                    context.CheckTimeout();

                    //Compute the Binding for every value
                    context.OutputMultiset.AddVariable(bindVar);
                    foreach (ISet s in context.InputMultiset.Sets)
                    {
                        ISet x = s.Copy();
                        try
                        {
                            INode val = bindExpr.Value(context, s.ID);
                            x.Add(bindVar, val);
                        }
                        catch (RdfQueryException)
                        {
                            //Equivalent to no assignment but the solution is preserved
                        }
                        context.OutputMultiset.Add(x);
                    }

                    //Remember to check for Timeouts during Lazy Evaluation
                    context.CheckTimeout();

                    //Decide whether to recurse or not
                    resultsFound = context.OutputMultiset.Count;
                    if (pattern < this._triplePatterns.Count - 1)
                    {
                        //Recurse then return
                        results = this.StreamingEvaluate(context, pattern + 1, out halt);
                        return(results);
                    }
                    else
                    {
                        halt = true;

                        //However many results we need we'll halt - previous patterns can call us again if they find more potential solutions
                        //for us to extend
                        return(context.OutputMultiset);
                    }
                }
            }
            else
            {
                throw new RdfQueryException("Encountered a " + temp.GetType().FullName + " which is not a lazily evaluable Pattern");
            }

            //If we found no possibles we return the null multiset
            if (resultsFound == 0)
            {
                return(new NullMultiset());
            }
            else
            {
                //Generate the final output and return it
                if (!modifies)
                {
                    if (context.InputMultiset.IsDisjointWith(context.OutputMultiset))
                    {
                        //Disjoint so do a Product
                        results = context.InputMultiset.ProductWithTimeout(context.OutputMultiset, context.RemainingTimeout);
                    }
                    else
                    {
                        //Normal Join
                        results = context.InputMultiset.Join(context.OutputMultiset);
                    }
                    context.OutputMultiset = results;
                }
                return(context.OutputMultiset);
            }
        }
        /// <summary>
        /// Evaluates the filtered product
        /// </summary>
        /// <param name="context">Evaluation Context</param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            BaseMultiset initialInput = context.InputMultiset;
            BaseMultiset lhsResults   = context.Evaluate(this._lhs);

            if (lhsResults is NullMultiset || lhsResults.IsEmpty)
            {
                //If LHS Results are Null/Empty then end result will always be null so short circuit
                context.OutputMultiset = new NullMultiset();
            }
            else
            {
                context.InputMultiset = initialInput;
                BaseMultiset rhsResults = context.Evaluate(this._rhs);
                if (rhsResults is NullMultiset || rhsResults.IsEmpty)
                {
                    //If RHS Results are Null/Empty then end results will always be null so short circuit
                    context.OutputMultiset = new NullMultiset();
                }
                else if (rhsResults is IdentityMultiset)
                {
                    //Apply Filter over LHS Results only - defer evaluation to filter implementation
                    context.InputMultiset = lhsResults;
                    UnaryExpressionFilter filter = new UnaryExpressionFilter(this._expr);
                    filter.Evaluate(context);
                    context.OutputMultiset = lhsResults;
                }
                else
                {
                    //Calculate the product applying the filter as we go
#if NET40 && !SILVERLIGHT
                    if (Options.UsePLinqEvaluation && this._expr.CanParallelise)
                    {
                        PartitionedMultiset partitionedSet;
                        SparqlResultBinder  binder = context.Binder;
                        if (lhsResults.Count >= rhsResults.Count)
                        {
                            partitionedSet = new PartitionedMultiset(lhsResults.Count, rhsResults.Count);
                            context.Binder = new LeviathanLeftJoinBinder(partitionedSet);
                            lhsResults.Sets.AsParallel().ForAll(x => this.EvalFilteredProduct(context, x, rhsResults, partitionedSet));
                        }
                        else
                        {
                            partitionedSet = new PartitionedMultiset(rhsResults.Count, lhsResults.Count);
                            context.Binder = new LeviathanLeftJoinBinder(partitionedSet);
                            rhsResults.Sets.AsParallel().ForAll(y => this.EvalFilteredProduct(context, y, lhsResults, partitionedSet));
                        }

                        context.Binder         = binder;
                        context.OutputMultiset = partitionedSet;
                    }
                    else
                    {
#endif
                    BaseMultiset productSet   = new Multiset();
                    SparqlResultBinder binder = context.Binder;
                    context.Binder = new LeviathanLeftJoinBinder(productSet);
                    foreach (ISet x in lhsResults.Sets)
                    {
                        foreach (ISet y in rhsResults.Sets)
                        {
                            ISet z = x.Join(y);
                            productSet.Add(z);
                            try
                            {
                                if (!this._expr.Evaluate(context, z.ID).AsSafeBoolean())
                                {
                                    //Means the expression evaluates to false so we discard the solution
                                    productSet.Remove(z.ID);
                                }
                            }
                            catch
                            {
                                //Means this solution does not meet the FILTER and can be discarded
                                productSet.Remove(z.ID);
                            }
                        }
                        //Remember to check for timeouts occassionaly
                        context.CheckTimeout();
                    }
                    context.Binder         = binder;
                    context.OutputMultiset = productSet;
#if NET40 && !SILVERLIGHT
                }
#endif
                }
            }
            return(context.OutputMultiset);
        }
Example #17
0
        /// <summary>
        /// Evaluates the Union
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            BaseMultiset initialInput = context.InputMultiset;
            BaseMultiset lhsResult = context.Evaluate(this._lhs);//this._lhs.Evaluate(context);
            context.CheckTimeout();

            context.InputMultiset = initialInput;
            BaseMultiset rhsResult = context.Evaluate(this._rhs);//this._rhs.Evaluate(context);
            context.CheckTimeout();

            context.OutputMultiset = lhsResult.Union(rhsResult);
            context.CheckTimeout();

            context.InputMultiset = context.OutputMultiset;
            return context.OutputMultiset;
        }
        /// <summary>
        /// Evaluates the Union
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            //Create a copy of the evaluation context for the RHS
            SparqlEvaluationContext context2 = new SparqlEvaluationContext(context.Query, context.Data, context.Processor);
            if (!(context.InputMultiset is IdentityMultiset))
            {
                context2.InputMultiset = new Multiset();
                foreach (ISet s in context.InputMultiset.Sets)
                {
                    context2.InputMultiset.Add(s.Copy());
                }
            }

            IGraph activeGraph = context.Data.ActiveGraph;
            IGraph defaultGraph = context.Data.DefaultGraph;

            ParallelEvaluateDelegate d = new ParallelEvaluateDelegate(this.ParallelEvaluate);
            IAsyncResult lhs = d.BeginInvoke(this._lhs, context, activeGraph, defaultGraph, null, null);
            IAsyncResult rhs = d.BeginInvoke(this._rhs, context2, activeGraph, defaultGraph, null, null);

            WaitHandle.WaitAll(new WaitHandle[] { lhs.AsyncWaitHandle, rhs.AsyncWaitHandle });

            bool rhsOk = false;
            try 
            {
                BaseMultiset lhsResult = d.EndInvoke(lhs);
                rhsOk = true;
                BaseMultiset rhsResult = d.EndInvoke(rhs);
                context.CheckTimeout();

                context.OutputMultiset = lhsResult.Union(rhsResult);
                context.CheckTimeout();

                context.InputMultiset = context.OutputMultiset;
                return context.OutputMultiset;
            }
            catch 
            {
                if (!rhsOk)
                {
                    //Clean up the RHS evaluation call if the LHS has errored
                    try
                    {
                        d.EndInvoke(rhs);
                    }
                    catch
                    {
                        //Ignore this error as we're already going to throw the other error
                    }
                }
                throw;
            }
        }
        /// <summary>
        /// Evalutes a Join
        /// </summary>
        /// <param name="context">Evaluation Context</param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            //Create a copy of the evaluation context for the RHS
            SparqlEvaluationContext context2 = new SparqlEvaluationContext(context.Query, context.Data, context.Processor);
            if (!(context.InputMultiset is IdentityMultiset))
            {
                context2.InputMultiset = new Multiset();
                foreach (ISet s in context.InputMultiset.Sets)
                {
                    context2.InputMultiset.Add(s.Copy());
                }
            }

            IGraph activeGraph = context.Data.ActiveGraph;
            IGraph defaultGraph = context.Data.DefaultGraph;

            //Start both executing asynchronously
            IAsyncResult lhs = this._d.BeginInvoke(this._lhs, context, activeGraph, defaultGraph, null, null);
            IAsyncResult rhs = this._d.BeginInvoke(this._rhs, context2, activeGraph, defaultGraph, new AsyncCallback(this.RhsCallback), null);

            //Wait on the LHS
            if (context.RemainingTimeout > 0)
            {
                lhs.AsyncWaitHandle.WaitOne(new TimeSpan(0, 0, 0, 0, (int)context.RemainingTimeout));
            }
            else
            {
                lhs.AsyncWaitHandle.WaitOne();
            }
            context.CheckTimeout();

            //Get the LHS result
            BaseMultiset lhsResult;
            try
            {
                lhsResult = this._d.EndInvoke(lhs);
            }
            catch
            {
                throw;
            }

            //If LHS came back as null/empty no need to wait for RHS to complete
            if (lhsResult is NullMultiset)
            {
                context.OutputMultiset = lhsResult;
            }
            else if (lhsResult.IsEmpty)
            {
                context.OutputMultiset = new NullMultiset();
            }
            else
            {
                //Wait for RHS to complete
                if (!rhs.IsCompleted)
                {
                    if (context.RemainingTimeout > 0)
                    {
                        rhs.AsyncWaitHandle.WaitOne(new TimeSpan(0, 0, 0, 0, (int)context.RemainingTimeout));
                    }
                    else
                    {
                        rhs.AsyncWaitHandle.WaitOne();
                    }
                    context.CheckTimeout();
                }

                if (this._rhsResult == null)
                {
                    if (this._rhsError != null) throw this._rhsError;
                    Thread.Sleep(10);
                }
                if (this._rhsResult == null) throw new RdfQueryException("Unknown error in parallel join evaluation, RHS is reported completed without errors but no result is available");

                //Compute the product of the two sides
                context.OutputMultiset = lhsResult.Product(this._rhsResult);
            }
            return context.OutputMultiset;
        }
Example #20
0
        /// <summary>
        /// Evaluates the BGP against the Evaluation Context.
        /// </summary>
        /// <param name="context">Evaluation Context.</param>
        /// <returns></returns>
        public virtual BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            if (_triplePatterns.Count > 0)
            {
                for (int i = 0; i < _triplePatterns.Count; i++)
                {
                    if (i == 0)
                    {
                        // If the 1st thing in a BGP is a BIND/LET/FILTER the Input becomes the Identity Multiset
                        if (_triplePatterns[i].PatternType == TriplePatternType.Filter || _triplePatterns[i].PatternType == TriplePatternType.BindAssignment || _triplePatterns[i].PatternType == TriplePatternType.LetAssignment)
                        {
                            if (_triplePatterns[i].PatternType == TriplePatternType.BindAssignment)
                            {
                                if (context.InputMultiset.ContainsVariable(((IAssignmentPattern)_triplePatterns[i]).VariableName))
                                {
                                    throw new RdfQueryException("Cannot use a BIND assigment to BIND to a variable that has previously been declared");
                                }
                            }
                            else
                            {
                                context.InputMultiset = new IdentityMultiset();
                            }
                        }
                    }

                    // Create a new Output Multiset
                    context.OutputMultiset = new Multiset();

                    _triplePatterns[i].Evaluate(context);

                    // If at any point we've got an Empty Multiset as our Output then we terminate BGP execution
                    if (context.OutputMultiset.IsEmpty)
                    {
                        break;
                    }

                    // Check for Timeout before attempting the Join
                    context.CheckTimeout();

                    // If this isn't the first Pattern we do Join/Product the Output to the Input
                    if (i > 0)
                    {
                        if (context.InputMultiset.IsDisjointWith(context.OutputMultiset))
                        {
                            // Disjoint so do a Product
                            context.OutputMultiset = context.InputMultiset.ProductWithTimeout(context.OutputMultiset, context.RemainingTimeout);
                        }
                        else
                        {
                            // Normal Join
                            context.OutputMultiset = context.InputMultiset.Join(context.OutputMultiset);
                        }
                    }

                    // Then the Input for the next Pattern is the Output from the previous Pattern
                    context.InputMultiset = context.OutputMultiset;
                }

                if (context.TrimTemporaryVariables)
                {
                    // Trim the Multiset - this eliminates any temporary variables
                    context.OutputMultiset.Trim();
                }
            }
            else
            {
                // For an Empty BGP we just return the Identity Multiset
                context.OutputMultiset = new IdentityMultiset();
            }

            // If we've ended with an Empty Multiset then we turn it into the Null Multiset
            // to indicate that this BGP did not match anything
            if (context.OutputMultiset is Multiset && context.OutputMultiset.IsEmpty)
            {
                context.OutputMultiset = new NullMultiset();
            }

            // Return the Output Multiset
            return(context.OutputMultiset);
        }
Example #21
0
        private BaseMultiset StreamingEvaluate(SparqlEvaluationContext context, int pattern, out bool halt)
        {
            halt = false;

            //Handle Empty BGPs
            if (pattern == 0 && this._triplePatterns.Count == 0)
            {
                context.OutputMultiset = new IdentityMultiset();
                return context.OutputMultiset;
            }

            BaseMultiset initialInput, localOutput, results;

            //Set up the Input and Output Multiset appropriately
            switch (pattern)
            {
                case 0:
                    //Input is as given and Output is new empty multiset
                    initialInput = context.InputMultiset;
                    localOutput = new Multiset();
                    break;

                case 1:
                    //Input becomes current Output and Output is new empty multiset
                    initialInput = context.OutputMultiset;
                    localOutput = new Multiset();
                    break;

                default:
                    //Input is join of previous input and ouput and Output is new empty multiset
                    if (context.InputMultiset.IsDisjointWith(context.OutputMultiset))
                    {
                        //Disjoint so do a Product
                        initialInput = context.InputMultiset.Product(context.OutputMultiset);
                    }
                    else
                    {
                        //Normal Join
                        initialInput = context.InputMultiset.Join(context.OutputMultiset);
                    }
                    localOutput = new Multiset();
                    break;
            }
            context.InputMultiset = initialInput;
            context.OutputMultiset = localOutput;

            //Get the Triple Pattern we're evaluating
            ITriplePattern temp = this._triplePatterns[pattern];
            int resultsFound = 0;

            if (temp is TriplePattern)
            {
                //Find the first Triple which matches the Pattern
                TriplePattern tp = (TriplePattern)temp;
                foreach (Triple t in tp.GetTriples(context))
                {
                    //Remember to check for Timeout during lazy evaluation
                    context.CheckTimeout();

                    if (tp.Accepts(context, t))
                    {
                        resultsFound++;
                        context.OutputMultiset.Add(tp.CreateResult(t));

                        //Recurse unless we're the last pattern
                        if (pattern < this._triplePatterns.Count - 1)
                        {
                            results = this.StreamingEvaluate(context, pattern + 1, out halt);

                            //If recursion leads to a halt then we halt and return immediately
                            if (halt) return results;

                            //Otherwise we need to keep going here
                            //So must reset our input and outputs before continuing
                            context.InputMultiset = initialInput;
                            context.OutputMultiset = new Multiset();
                            resultsFound--;
                        }
                        else
                        {
                            //If we're at the last pattern and we've found a match then we can halt
                            halt = true;

                            //Generate the final output and return it
                            if (context.InputMultiset.IsDisjointWith(context.OutputMultiset))
                            {
                                //Disjoint so do a Product
                                context.OutputMultiset = context.InputMultiset.ProductWithTimeout(context.OutputMultiset, context.QueryTimeout - context.QueryTime);
                            }
                            else
                            {
                                //Normal Join
                                context.OutputMultiset = context.InputMultiset.Join(context.OutputMultiset);
                            }
                            return context.OutputMultiset;
                        }
                    }
                }
            }
            else if (temp is FilterPattern)
            {
                FilterPattern fp = (FilterPattern)temp;
                ISparqlFilter filter = fp.Filter;
                ISparqlExpression expr = filter.Expression;

                //Find the first result of those we've got so far that matches
                if (context.InputMultiset is IdentityMultiset || context.InputMultiset.IsEmpty)
                {
                    try
                    {
                        //If the Input is the Identity Multiset then the Output is either
                        //the Identity/Null Multiset depending on whether the Expression evaluates to true
                        if (expr.EffectiveBooleanValue(context, 0))
                        {
                            context.OutputMultiset = new IdentityMultiset();
                        }
                        else
                        {
                            context.OutputMultiset = new NullMultiset();
                        }
                    }
                    catch
                    {
                        //If Expression fails to evaluate then result is NullMultiset
                        context.OutputMultiset = new NullMultiset();
                    }
                } 
                else
                {
                    foreach (int id in context.InputMultiset.SetIDs)
                    {
                        //Remember to check for Timeout during lazy evaluation
                        context.CheckTimeout();

                        try
                        {
                            if (expr.EffectiveBooleanValue(context, id))
                            {
                                resultsFound++;
                                context.OutputMultiset.Add(context.InputMultiset[id]);

                                //Recurse unless we're the last pattern
                                if (pattern < this._triplePatterns.Count - 1)
                                {
                                    results = this.StreamingEvaluate(context, pattern + 1, out halt);

                                    //If recursion leads to a halt then we halt and return immediately
                                    if (halt) return results;

                                    //Otherwise we need to keep going here
                                    //So must reset our input and outputs before continuing
                                    context.InputMultiset = initialInput;
                                    context.OutputMultiset = new Multiset();
                                    resultsFound--;
                                }
                                else
                                {
                                    //If we're at the last pattern and we've found a match then we can halt
                                    halt = true;

                                    //Generate the final output and return it
                                    if (context.InputMultiset.IsDisjointWith(context.OutputMultiset))
                                    {
                                        //Disjoint so do a Product
                                        context.OutputMultiset = context.InputMultiset.ProductWithTimeout(context.OutputMultiset, context.RemainingTimeout);
                                    }
                                    else
                                    {
                                        //Normal Join
                                        context.OutputMultiset = context.InputMultiset.Join(context.OutputMultiset);
                                    }
                                    return context.OutputMultiset;
                                }
                            }
                        }
                        catch
                        {
                            //Ignore expression evaluation errors
                        }
                    }
                }
            }

            //If we found no possibles we return the null multiset
            if (resultsFound == 0) return new NullMultiset();

            //We should never reach here so throw an error to that effect
            //The reason we'll never reach here is that this method should always return earlier
            throw new RdfQueryException("Unexpected control flow in evaluating a Streamed BGP for an ASK query");
        }
Example #22
0
        /// <summary>
        /// Evaluates the Ask Union
        /// </summary>
        /// <param name="context">Evaluation Context</param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            BaseMultiset initialInput = context.InputMultiset;
            BaseMultiset lhsResult = context.Evaluate(this._lhs);//this._lhs.Evaluate(context);
            context.CheckTimeout();

            if (lhsResult.IsEmpty)
            {
                //Only evaluate the RHS if the LHS was empty
                context.InputMultiset = initialInput;
                BaseMultiset rhsResult = context.Evaluate(this._rhs);//this._rhs.Evaluate(context);
                context.CheckTimeout();

                context.OutputMultiset = lhsResult.Union(rhsResult);
                context.CheckTimeout();

                context.InputMultiset = context.OutputMultiset;
            }
            else
            {
                context.OutputMultiset = lhsResult;
            }
            return context.OutputMultiset;
        }
Example #23
0
        /// <summary>
        /// Evaluates the Service Clause by generating instance(s) of <see cref="SparqlRemoteEndpoint">SparqlRemoteEndpoint</see> as required and issuing the query to the remote endpoint(s)
        /// </summary>
        /// <param name="context">Evaluation Context</param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            bool bypassSilent = false;
            try
            {
            #if SILVERLIGHT
                throw new PlatformNotSupportedException("SERVICE is not currently supported under Silverlight");
            #else
                SparqlRemoteEndpoint endpoint;
                Uri endpointUri;
                String baseUri = (context.Query.BaseUri == null) ? String.Empty : context.Query.BaseUri.ToString();
                SparqlParameterizedString sparqlQuery = new SparqlParameterizedString("SELECT * WHERE ");

                String pattern = this._pattern.ToString();
                pattern = pattern.Substring(pattern.IndexOf('{'));
                sparqlQuery.CommandText += pattern;

                //Pass through LIMIT and OFFSET to the remote service
                if (context.Query.Limit >= 0)
                {
                    //Calculate a LIMIT which is the LIMIT plus the OFFSET
                    //We'll apply OFFSET locally so don't pass that through explicitly
                    int limit = context.Query.Limit;
                    if (context.Query.Offset > 0) limit += context.Query.Offset;
                    sparqlQuery.CommandText += " LIMIT " + limit;
                }

                //Select which service to use
                if (this._endpointSpecifier.TokenType == Token.URI)
                {
                    endpointUri = UriFactory.Create(Tools.ResolveUri(this._endpointSpecifier.Value, baseUri));
                    endpoint = new SparqlRemoteEndpoint(endpointUri);
                }
                else if (this._endpointSpecifier.TokenType == Token.VARIABLE)
                {
                    //Get all the URIs that are bound to this Variable in the Input
                    String var = this._endpointSpecifier.Value.Substring(1);
                    if (!context.InputMultiset.ContainsVariable(var)) throw new RdfQueryException("Cannot evaluate a SERVICE clause which uses a Variable as the Service specifier when the Variable is unbound");
                    List<IUriNode> services = new List<IUriNode>();
                    foreach (ISet s in context.InputMultiset.Sets)
                    {
                        if (s.ContainsVariable(var))
                        {
                            if (s[var].NodeType == NodeType.Uri)
                            {
                                services.Add((IUriNode)s[var]);
                            }
                        }
                    }
                    services = services.Distinct().ToList();

                    //Now generate a Federated Remote Endpoint
                    List<SparqlRemoteEndpoint> serviceEndpoints = new List<SparqlRemoteEndpoint>();
                    services.ForEach(u => serviceEndpoints.Add(new SparqlRemoteEndpoint(u.Uri)));
                    endpoint = new FederatedSparqlRemoteEndpoint(serviceEndpoints);
                }
                else
                {
                    //Note that we must bypass the SILENT operator in this case as this is not an evaluation failure
                    //but a query syntax error
                    bypassSilent = true;
                    throw new RdfQueryException("SERVICE Specifier must be a URI/Variable Token but a " + this._endpointSpecifier.GetType().ToString() + " Token was provided");
                }

                //Where possible do substitution and execution to get accurate and correct SERVICE results
                context.OutputMultiset = new Multiset();
                List<String> existingVars = (from v in this._pattern.Variables
                                             where context.InputMultiset.ContainsVariable(v)
                                             select v).ToList();

                if (existingVars.Any() || context.Query.Bindings != null)
                {
                    //Pre-bound variables/BINDINGS clause so do substitution and execution

                    //Build the set of possible bindings
                    HashSet<ISet> bindings = new HashSet<ISet>();
                    if (context.Query.Bindings != null && !this._pattern.Variables.IsDisjoint(context.Query.Bindings.Variables))
                    {
                        //Possible Bindings comes from BINDINGS clause
                        //In this case each possibility is a distinct binding tuple defined in the BINDINGS clause
                        foreach (BindingTuple tuple in context.Query.Bindings.Tuples)
                        {
                            bindings.Add(new Set(tuple));
                        }
                    }
                    else
                    {
                        //Possible Bindings get built from current input (if there was a BINDINGS clause the variables it defines are not in this SERVICE clause)
                        //In this case each possibility only contains Variables bound so far
                        foreach (ISet s in context.InputMultiset.Sets)
                        {
                            Set t = new Set();
                            foreach (String var in existingVars)
                            {
                                t.Add(var, s[var]);
                            }
                            bindings.Add(t);
                        }
                    }

                    //Execute the Query for every possible Binding and build up our Output Multiset from all the results
                    foreach (ISet s in bindings)
                    {
                        //Q: Should we continue processing here if and when we hit an error?

                        foreach (String var in s.Variables)
                        {
                            sparqlQuery.SetVariable(var, s[var]);
                        }
                        SparqlResultSet results = endpoint.QueryWithResultSet(sparqlQuery.ToString());
                        context.CheckTimeout();

                        foreach (SparqlResult r in results)
                        {
                            Set t = new Set(r);
                            foreach (String var in s.Variables)
                            {
                                t.Add(var, s[var]);
                            }
                            context.OutputMultiset.Add(t);
                        }
                    }

                    return context.OutputMultiset;
                }
                else
                {
                    //No pre-bound variables/BINDINGS clause so just execute the query

                    //Try and get a Result Set from the Service
                    SparqlResultSet results = endpoint.QueryWithResultSet(sparqlQuery.ToString());

                    //Transform this Result Set back into a Multiset
                    foreach (SparqlResult r in results.Results)
                    {
                        context.OutputMultiset.Add(new Set(r));
                    }

                    return context.OutputMultiset;
                }
            #endif
            }
            catch (Exception ex)
            {
                if (this._silent && !bypassSilent)
                {

                    //If Evaluation Errors are SILENT is specified then a Multiset containing a single set with all values unbound is returned
                    //Unless some of the SPARQL queries did return results in which we just return the results we did obtain
                    if (context.OutputMultiset.IsEmpty)
                    {
                        Set s = new Set();
                        foreach (String var in this._pattern.Variables.Distinct())
                        {
                            s.Add(var, null);
                        }
                        context.OutputMultiset.Add(s);
                    }
                    return context.OutputMultiset;
                }
                else
                {
                    throw new RdfQueryException("Query execution failed because evaluating a SERVICE clause failed - this may be due to an error with the remote service", ex);
                }
            }
        }
Example #24
0
        /// <summary>
        /// Evaluates the BGP against the Evaluation Context
        /// </summary>
        /// <param name="context">Evaluation Context</param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            if (this._triplePatterns.Count > 0)
            {
                for (int i = 0; i < this._triplePatterns.Count; i++)
                {
                    if (i == 0)
                    {
                        //If the 1st thing in a BGP is a BIND/LET/FILTER the Input becomes the Identity Multiset
                        if (this._triplePatterns[i] is FilterPattern || this._triplePatterns[i] is BindPattern || this._triplePatterns[i] is LetPattern)
                        {
                            if (this._triplePatterns[i] is BindPattern)
                            {
                                if (context.InputMultiset.ContainsVariable(((BindPattern)this._triplePatterns[i]).VariableName)) throw new RdfQueryException("Cannot use a BIND assigment to BIND to a variable that has previously been declared");
                            }
                            else
                            {
                                context.InputMultiset = new IdentityMultiset();
                            }
                        }
                    }

                    //Create a new Output Multiset
                    context.OutputMultiset = new Multiset();

                    this._triplePatterns[i].Evaluate(context);

                    //If at any point we've got an Empty Multiset as our Output then we terminate BGP execution
                    if (context.OutputMultiset.IsEmpty) break;

                    //Check for Timeout before attempting the Join
                    context.CheckTimeout();

                    //If this isn't the first Pattern we do Join/Product the Output to the Input
                    if (i > 0)
                    {
                        if (context.InputMultiset.IsDisjointWith(context.OutputMultiset))
                        {
                            //Disjoint so do a Product
                            context.OutputMultiset = context.InputMultiset.ProductWithTimeout(context.OutputMultiset, context.RemainingTimeout);
                        }
                        else
                        {
                            //Normal Join
                            context.OutputMultiset = context.InputMultiset.Join(context.OutputMultiset);
                        }
                    }

                    //Then the Input for the next Pattern is the Output from the previous Pattern
                    context.InputMultiset = context.OutputMultiset;
                }

                if (context.TrimTemporaryVariables)
                {
                    //Trim the Multiset - this eliminates any temporary variables
                    context.OutputMultiset.Trim();
                }
            }
            else
            {
                //For an Empty BGP we just return the Identity Multiset
                context.OutputMultiset = new IdentityMultiset();
            }

            //If we've ended with an Empty Multiset then we turn it into the Null Multiset
            //to indicate that this BGP did not match anything
            if (context.OutputMultiset is Multiset && context.OutputMultiset.IsEmpty) context.OutputMultiset = new NullMultiset();

            //Return the Output Multiset
            return context.OutputMultiset;
        }
        /// <summary>
        /// Evalutes a Join
        /// </summary>
        /// <param name="context">Evaluation Context</param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            //Create a copy of the evaluation context for the RHS
            SparqlEvaluationContext context2 = new SparqlEvaluationContext(context.Query, context.Data, context.Processor);

            if (!(context.InputMultiset is IdentityMultiset))
            {
                context2.InputMultiset = new Multiset();
                foreach (ISet s in context.InputMultiset.Sets)
                {
                    context2.InputMultiset.Add(s.Copy());
                }
            }

            List <Uri> activeGraphs  = context.Data.ActiveGraphUris.ToList();
            List <Uri> defaultGraphs = context.Data.DefaultGraphUris.ToList();

            //Start both executing asynchronously
            IAsyncResult lhs = this._d.BeginInvoke(this._lhs, context, activeGraphs, defaultGraphs, null, null);
            IAsyncResult rhs = this._d.BeginInvoke(this._rhs, context2, activeGraphs, defaultGraphs, new AsyncCallback(this.RhsCallback), null);

            //Wait on the LHS
            if (context.RemainingTimeout > 0)
            {
                lhs.AsyncWaitHandle.WaitOne(new TimeSpan(0, 0, 0, 0, (int)context.RemainingTimeout));
            }
            else
            {
                lhs.AsyncWaitHandle.WaitOne();
            }
            context.CheckTimeout();

            //Get the LHS result
            BaseMultiset lhsResult;

            try
            {
                lhsResult = this._d.EndInvoke(lhs);
            }
            catch
            {
                throw;
            }

            //If LHS came back as null/empty no need to wait for RHS to complete
            if (lhsResult is NullMultiset)
            {
                context.OutputMultiset = lhsResult;
            }
            else if (lhsResult.IsEmpty)
            {
                context.OutputMultiset = new NullMultiset();
            }
            else
            {
                //Wait for RHS to complete
                if (!rhs.IsCompleted)
                {
                    if (context.RemainingTimeout > 0)
                    {
                        rhs.AsyncWaitHandle.WaitOne(new TimeSpan(0, 0, 0, 0, (int)context.RemainingTimeout));
                    }
                    else
                    {
                        rhs.AsyncWaitHandle.WaitOne();
                    }
                    context.CheckTimeout();
                }

                if (this._rhsResult == null)
                {
                    if (this._rhsError != null)
                    {
                        throw this._rhsError;
                    }
#if !PORTABLE // No Thread.Sleep() in PCL
                    Thread.Sleep(10);
#endif
                }
                if (this._rhsResult == null)
                {
                    throw new RdfQueryException("Unknown error in parallel join evaluation, RHS is reported completed without errors but no result is available");
                }

                //Compute the product of the two sides
                context.OutputMultiset = lhsResult.Product(this._rhsResult);
            }
            return(context.OutputMultiset);
        }
Example #26
0
        /// <summary>
        /// Evaluates the Lazy Union
        /// </summary>
        /// <param name="context">Evaluation Context</param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            BaseMultiset initialInput = context.InputMultiset;
            if (this._lhs is Extend || this._rhs is Extend) initialInput = new IdentityMultiset();

            context.InputMultiset = initialInput;
            BaseMultiset lhsResult = context.Evaluate(this._lhs);//this._lhs.Evaluate(context);
            context.CheckTimeout();

            if (lhsResult.Count >= this._requiredResults || this._requiredResults == -1)
            {
                //Only evaluate the RHS if the LHS didn't yield sufficient results
                context.InputMultiset = initialInput;
                BaseMultiset rhsResult = context.Evaluate(this._rhs);//this._rhs.Evaluate(context);
                context.CheckTimeout();

                context.OutputMultiset = lhsResult.Union(rhsResult);
                context.CheckTimeout();

                context.InputMultiset = context.OutputMultiset;
            }
            else
            {
                context.OutputMultiset = lhsResult;
            }
            return context.OutputMultiset;
        }
Example #27
0
        private BaseMultiset StreamingEvaluate(SparqlEvaluationContext context, int pattern, out bool halt)
        {
            halt = false;

            //Handle Empty BGPs
            if (pattern == 0 && this._triplePatterns.Count == 0)
            {
                context.OutputMultiset = new IdentityMultiset();
                return(context.OutputMultiset);
            }

            BaseMultiset initialInput, localOutput, results;

            //Set up the Input and Output Multiset appropriately
            switch (pattern)
            {
            case 0:
                //Input is as given and Output is new empty multiset
                initialInput = context.InputMultiset;
                localOutput  = new Multiset();
                break;

            case 1:
                //Input becomes current Output and Output is new empty multiset
                initialInput = context.OutputMultiset;
                localOutput  = new Multiset();
                break;

            default:
                //Input is join of previous input and ouput and Output is new empty multiset
                if (context.InputMultiset.IsDisjointWith(context.OutputMultiset))
                {
                    //Disjoint so do a Product
                    initialInput = context.InputMultiset.Product(context.OutputMultiset);
                }
                else
                {
                    //Normal Join
                    initialInput = context.InputMultiset.Join(context.OutputMultiset);
                }
                localOutput = new Multiset();
                break;
            }
            context.InputMultiset  = initialInput;
            context.OutputMultiset = localOutput;

            //Get the Triple Pattern we're evaluating
            ITriplePattern temp         = this._triplePatterns[pattern];
            int            resultsFound = 0;

            if (temp.PatternType == TriplePatternType.Match)
            {
                //Find the first Triple which matches the Pattern
                IMatchTriplePattern tp = (IMatchTriplePattern)temp;
                foreach (Triple t in tp.GetTriples(context))
                {
                    //Remember to check for Timeout during lazy evaluation
                    context.CheckTimeout();

                    if (tp.Accepts(context, t))
                    {
                        resultsFound++;
                        context.OutputMultiset.Add(tp.CreateResult(t));

                        //Recurse unless we're the last pattern
                        if (pattern < this._triplePatterns.Count - 1)
                        {
                            results = this.StreamingEvaluate(context, pattern + 1, out halt);

                            //If recursion leads to a halt then we halt and return immediately
                            if (halt)
                            {
                                return(results);
                            }

                            //Otherwise we need to keep going here
                            //So must reset our input and outputs before continuing
                            context.InputMultiset  = initialInput;
                            context.OutputMultiset = new Multiset();
                            resultsFound--;
                        }
                        else
                        {
                            //If we're at the last pattern and we've found a match then we can halt
                            halt = true;

                            //Generate the final output and return it
                            if (context.InputMultiset.IsDisjointWith(context.OutputMultiset))
                            {
                                //Disjoint so do a Product
                                context.OutputMultiset = context.InputMultiset.ProductWithTimeout(context.OutputMultiset, context.QueryTimeout - context.QueryTime);
                            }
                            else
                            {
                                //Normal Join
                                context.OutputMultiset = context.InputMultiset.Join(context.OutputMultiset);
                            }
                            return(context.OutputMultiset);
                        }
                    }
                }
            }
            else if (temp.PatternType == TriplePatternType.Filter)
            {
                IFilterPattern    fp     = (IFilterPattern)temp;
                ISparqlFilter     filter = fp.Filter;
                ISparqlExpression expr   = filter.Expression;

                //Find the first result of those we've got so far that matches
                if (context.InputMultiset is IdentityMultiset || context.InputMultiset.IsEmpty)
                {
                    try
                    {
                        //If the Input is the Identity Multiset then the Output is either
                        //the Identity/Null Multiset depending on whether the Expression evaluates to true
                        if (expr.Evaluate(context, 0).AsSafeBoolean())
                        {
                            context.OutputMultiset = new IdentityMultiset();
                        }
                        else
                        {
                            context.OutputMultiset = new NullMultiset();
                        }
                    }
                    catch
                    {
                        //If Expression fails to evaluate then result is NullMultiset
                        context.OutputMultiset = new NullMultiset();
                    }
                }
                else
                {
                    foreach (int id in context.InputMultiset.SetIDs)
                    {
                        //Remember to check for Timeout during lazy evaluation
                        context.CheckTimeout();

                        try
                        {
                            if (expr.Evaluate(context, id).AsSafeBoolean())
                            {
                                resultsFound++;
                                context.OutputMultiset.Add(context.InputMultiset[id].Copy());

                                //Recurse unless we're the last pattern
                                if (pattern < this._triplePatterns.Count - 1)
                                {
                                    results = this.StreamingEvaluate(context, pattern + 1, out halt);

                                    //If recursion leads to a halt then we halt and return immediately
                                    if (halt)
                                    {
                                        return(results);
                                    }

                                    //Otherwise we need to keep going here
                                    //So must reset our input and outputs before continuing
                                    context.InputMultiset  = initialInput;
                                    context.OutputMultiset = new Multiset();
                                    resultsFound--;
                                }
                                else
                                {
                                    //If we're at the last pattern and we've found a match then we can halt
                                    halt = true;

                                    //Generate the final output and return it
                                    if (context.InputMultiset.IsDisjointWith(context.OutputMultiset))
                                    {
                                        //Disjoint so do a Product
                                        context.OutputMultiset = context.InputMultiset.ProductWithTimeout(context.OutputMultiset, context.RemainingTimeout);
                                    }
                                    else
                                    {
                                        //Normal Join
                                        context.OutputMultiset = context.InputMultiset.Join(context.OutputMultiset);
                                    }
                                    return(context.OutputMultiset);
                                }
                            }
                        }
                        catch
                        {
                            //Ignore expression evaluation errors
                        }
                    }
                }
            }

            //If we found no possibles we return the null multiset
            if (resultsFound == 0)
            {
                return(new NullMultiset());
            }

            //We should never reach here so throw an error to that effect
            //The reason we'll never reach here is that this method should always return earlier
            throw new RdfQueryException("Unexpected control flow in evaluating a Streamed BGP for an ASK query");
        }
Example #28
0
        /// <summary>
        /// Evalutes a Join.
        /// </summary>
        /// <param name="context">Evaluation Context.</param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            // Create a copy of the evaluation context for the RHS
            SparqlEvaluationContext context2 =
                new SparqlEvaluationContext(context.Query, context.Data, context.Processor);

            if (!(context.InputMultiset is IdentityMultiset))
            {
                context2.InputMultiset = new Multiset();
                foreach (ISet s in context.InputMultiset.Sets)
                {
                    context2.InputMultiset.Add(s.Copy());
                }
            }

            List <Uri> activeGraphs  = context.Data.ActiveGraphUris.ToList();
            List <Uri> defaultGraphs = context.Data.DefaultGraphUris.ToList();

            // Start both executing asynchronously
            var cts = new CancellationTokenSource();
            var cancellationToken = cts.Token;
            var lhsEvaluation     =
                Task.Factory.StartNew(() => ParallelEvaluate(_lhs, context, activeGraphs, defaultGraphs),
                                      cancellationToken);
            var rhsEvaluation =
                Task.Factory.StartNew(() => ParallelEvaluate(_rhs, context2, activeGraphs, defaultGraphs),
                                      cancellationToken);
            var evaluationTasks = new Task[] { lhsEvaluation, rhsEvaluation };

            try
            {
                if (context.RemainingTimeout > 0)
                {
                    Task.WaitAny(evaluationTasks, (int)context.RemainingTimeout, cancellationToken);
                }
                else
                {
                    Task.WaitAny(evaluationTasks, cancellationToken);
                }

                var firstResult = lhsEvaluation.IsCompleted ? lhsEvaluation.Result : rhsEvaluation.Result;
                if (firstResult == null)
                {
                    context.OutputMultiset = new NullMultiset();
                    cts.Cancel();
                }
                else if (firstResult is NullMultiset)
                {
                    context.OutputMultiset = new NullMultiset();
                    cts.Cancel();
                }
                else
                {
                    context.CheckTimeout();
                    if (context.RemainingTimeout > 0)
                    {
                        Task.WaitAll(evaluationTasks, (int)context.RemainingTimeout, cancellationToken);
                    }
                    else
                    {
                        Task.WaitAll(evaluationTasks, cancellationToken);
                    }

                    var lhsResult = lhsEvaluation.Result;
                    var rhsResult = rhsEvaluation.Result;
                    if (lhsResult is NullMultiset)
                    {
                        context.OutputMultiset = lhsResult;
                    }
                    else if (rhsResult is NullMultiset)
                    {
                        context.OutputMultiset = rhsResult;
                    }
                    else if (lhsResult == null || rhsResult == null)
                    {
                        context.OutputMultiset = new NullMultiset();
                    }
                    else
                    {
                        context.OutputMultiset = lhsResult.Product(rhsResult);
                    }
                }

                return(context.OutputMultiset);
            }
            catch (OperationCanceledException)
            {
                throw new RdfQueryTimeoutException("Query Execution Time exceeded the Timeout of " +
                                                   context.QueryTimeout + "ms, query aborted after " +
                                                   context.QueryTime + "ms");
            }
            catch (AggregateException ex)
            {
                var firstCause = ex.InnerExceptions.FirstOrDefault();
                if (firstCause is RdfException)
                {
                    throw firstCause;
                }
                throw new RdfQueryException("Error in parallel join evaluation.", ex);
            }
            catch (RdfException)
            {
                throw;
            }
            catch (Exception ex)
            {
                throw new RdfQueryException("Error in parallel join evaluation.", ex);
            }
        }
Example #29
0
        /// <summary>
        /// Evaluates the Service Clause by generating instance(s) of <see cref="SparqlRemoteEndpoint">SparqlRemoteEndpoint</see> as required and issuing the query to the remote endpoint(s).
        /// </summary>
        /// <param name="context">Evaluation Context.</param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            bool bypassSilent = false;

            try
            {
                SparqlRemoteEndpoint endpoint;
                Uri    endpointUri;
                String baseUri = (context.Query.BaseUri == null) ? String.Empty : context.Query.BaseUri.AbsoluteUri;
                SparqlParameterizedString sparqlQuery = new SparqlParameterizedString("SELECT * WHERE ");

                String pattern = _pattern.ToString();
                pattern = pattern.Substring(pattern.IndexOf('{'));
                sparqlQuery.CommandText += pattern;

                // Pass through LIMIT and OFFSET to the remote service
                if (context.Query.Limit >= 0)
                {
                    // Calculate a LIMIT which is the LIMIT plus the OFFSET
                    // We'll apply OFFSET locally so don't pass that through explicitly
                    int limit = context.Query.Limit;
                    if (context.Query.Offset > 0)
                    {
                        limit += context.Query.Offset;
                    }
                    sparqlQuery.CommandText += " LIMIT " + limit;
                }

                // Select which service to use
                if (_endpointSpecifier.TokenType == Token.URI)
                {
                    endpointUri = UriFactory.Create(Tools.ResolveUri(_endpointSpecifier.Value, baseUri));
                    endpoint    = new SparqlRemoteEndpoint(endpointUri);
                }
                else if (_endpointSpecifier.TokenType == Token.VARIABLE)
                {
                    // Get all the URIs that are bound to this Variable in the Input
                    String var = _endpointSpecifier.Value.Substring(1);
                    if (!context.InputMultiset.ContainsVariable(var))
                    {
                        throw new RdfQueryException("Cannot evaluate a SERVICE clause which uses a Variable as the Service specifier when the Variable is unbound");
                    }
                    List <IUriNode> services = new List <IUriNode>();
                    foreach (ISet s in context.InputMultiset.Sets)
                    {
                        if (s.ContainsVariable(var))
                        {
                            if (s[var].NodeType == NodeType.Uri)
                            {
                                services.Add((IUriNode)s[var]);
                            }
                        }
                    }
                    services = services.Distinct().ToList();

                    // Now generate a Federated Remote Endpoint
                    List <SparqlRemoteEndpoint> serviceEndpoints = new List <SparqlRemoteEndpoint>();
                    services.ForEach(u => serviceEndpoints.Add(new SparqlRemoteEndpoint(u.Uri)));
                    endpoint = new FederatedSparqlRemoteEndpoint(serviceEndpoints);
                }
                else
                {
                    // Note that we must bypass the SILENT operator in this case as this is not an evaluation failure
                    // but a query syntax error
                    bypassSilent = true;
                    throw new RdfQueryException("SERVICE Specifier must be a URI/Variable Token but a " + _endpointSpecifier.GetType().ToString() + " Token was provided");
                }

                // Where possible do substitution and execution to get accurate and correct SERVICE results
                context.OutputMultiset = new Multiset();
                List <String> existingVars = (from v in _pattern.Variables
                                              where context.InputMultiset.ContainsVariable(v)
                                              select v).ToList();

                if (existingVars.Any() || context.Query.Bindings != null)
                {
                    // Pre-bound variables/BINDINGS clause so do substitution and execution

                    // Build the set of possible bindings
                    HashSet <ISet> bindings = new HashSet <ISet>();
                    if (context.Query.Bindings != null && !_pattern.Variables.IsDisjoint(context.Query.Bindings.Variables))
                    {
                        // Possible Bindings comes from BINDINGS clause
                        // In this case each possibility is a distinct binding tuple defined in the BINDINGS clause
                        foreach (BindingTuple tuple in context.Query.Bindings.Tuples)
                        {
                            bindings.Add(new Set(tuple));
                        }
                    }
                    else
                    {
                        // Possible Bindings get built from current input (if there was a BINDINGS clause the variables it defines are not in this SERVICE clause)
                        // In this case each possibility only contains Variables bound so far
                        foreach (ISet s in context.InputMultiset.Sets)
                        {
                            Set t = new Set();
                            foreach (String var in existingVars)
                            {
                                t.Add(var, s[var]);
                            }
                            bindings.Add(t);
                        }
                    }

                    // Execute the Query for every possible Binding and build up our Output Multiset from all the results
                    foreach (ISet s in bindings)
                    {
                        // Q: Should we continue processing here if and when we hit an error?

                        foreach (String var in s.Variables)
                        {
                            sparqlQuery.SetVariable(var, s[var]);
                        }
                        SparqlResultSet results = endpoint.QueryWithResultSet(sparqlQuery.ToString());
                        context.CheckTimeout();

                        foreach (SparqlResult r in results)
                        {
                            Set t = new Set(r);
                            foreach (String var in s.Variables)
                            {
                                t.Add(var, s[var]);
                            }
                            context.OutputMultiset.Add(t);
                        }
                    }

                    return(context.OutputMultiset);
                }
                else
                {
                    // No pre-bound variables/BINDINGS clause so just execute the query

                    // Try and get a Result Set from the Service
                    SparqlResultSet results = endpoint.QueryWithResultSet(sparqlQuery.ToString());

                    // Transform this Result Set back into a Multiset
                    foreach (SparqlResult r in results.Results)
                    {
                        context.OutputMultiset.Add(new Set(r));
                    }

                    return(context.OutputMultiset);
                }
            }
            catch (Exception ex)
            {
                if (_silent && !bypassSilent)
                {
                    // If Evaluation Errors are SILENT is specified then a Multiset containing a single set with all values unbound is returned
                    // Unless some of the SPARQL queries did return results in which we just return the results we did obtain
                    if (context.OutputMultiset.IsEmpty)
                    {
                        Set s = new Set();
                        foreach (String var in _pattern.Variables.Distinct())
                        {
                            s.Add(var, null);
                        }
                        context.OutputMultiset.Add(s);
                    }
                    return(context.OutputMultiset);
                }
                else
                {
                    throw new RdfQueryException("Query execution failed because evaluating a SERVICE clause failed - this may be due to an error with the remote service", ex);
                }
            }
        }
Example #30
0
        private BaseMultiset StreamingEvaluate(SparqlEvaluationContext context, int pattern, out bool halt)
        {
            halt = false;

            //Handle Empty BGPs
            if (pattern == 0 && this._triplePatterns.Count == 0)
            {
                context.OutputMultiset = new IdentityMultiset();
                return context.OutputMultiset;
            }

            BaseMultiset initialInput, localOutput, results = null;

            //Determine whether the Pattern modifies the existing Input rather than joining to it
            bool modifies = (this._triplePatterns[pattern] is FilterPattern);
            bool extended = (pattern > 0 && this._triplePatterns[pattern-1] is BindPattern);
            bool modified = (pattern > 0 && this._triplePatterns[pattern-1] is FilterPattern);

            //Set up the Input and Output Multiset appropriately
            switch (pattern)
            {
                case 0:
                    //Input is as given and Output is new empty multiset
                    if (!modifies)
                    {
                        initialInput = context.InputMultiset;
                    }
                    else
                    {
                        //If the Pattern will modify the Input and is the first thing in the BGP then it actually modifies a new empty input
                        //This takes care of FILTERs being out of scope
                        initialInput = new Multiset();
                    }
                    localOutput = new Multiset();
                    break;

                case 1:
                    //Input becomes current Output and Output is new empty multiset
                    initialInput = context.OutputMultiset;
                    localOutput = new Multiset();
                    break;

                default:
                    if (!extended && !modified)
                    {
                        //Input is join of previous input and output and Output is new empty multiset
                        if (context.InputMultiset.IsDisjointWith(context.OutputMultiset))
                        {
                            //Disjoint so do a Product
                            initialInput = context.InputMultiset.ProductWithTimeout(context.OutputMultiset, context.RemainingTimeout);
                        }
                        else
                        {
                            //Normal Join
                            initialInput = context.InputMultiset.Join(context.OutputMultiset);
                        }
                    }
                    else
                    {
                        initialInput = context.OutputMultiset;
                    }
                    localOutput = new Multiset();
                    break;
            }
            context.InputMultiset = initialInput;
            context.OutputMultiset = localOutput;

            //Get the Triple Pattern we're evaluating
            ITriplePattern temp = this._triplePatterns[pattern];
            int resultsFound = 0;
            int prevResults = -1;

            if (temp is TriplePattern)
            {
                //Find the first Triple which matches the Pattern
                TriplePattern tp = (TriplePattern)temp;
                IEnumerable<Triple> ts = tp.GetTriples(context);

                //In the case that we're lazily evaluating an optimisable ORDER BY then
                //we need to apply OrderBy()'s to our enumeration
                //This only applies to the 1st pattern
                if (pattern == 0)
                {
                    if (context.Query != null)
                    {
                        if (context.Query.OrderBy != null && context.Query.IsOptimisableOrderBy)
                        {
                            IComparer<Triple> comparer = context.Query.OrderBy.GetComparer(tp);
                            if (comparer != null)
                            {
                                ts = ts.OrderBy(t => t, comparer);
                            }
                            else
                            {
                                //Can't get a comparer so can't optimise
                                this._requiredResults = -1;
                            }
                        }
                    }
                }

                foreach (Triple t in ts)
                {
                    //Remember to check for Timeouts during Lazy Evaluation
                    context.CheckTimeout();

                    if (tp.Accepts(context, t))
                    {
                        resultsFound++;
                        if (tp.IndexType == TripleIndexType.NoVariables)
                        {
                            localOutput = new IdentityMultiset();
                            context.OutputMultiset = localOutput;
                        }
                        else
                        {
                            context.OutputMultiset.Add(tp.CreateResult(t));
                        }

                        //Recurse unless we're the last pattern
                        if (pattern < this._triplePatterns.Count - 1)
                        {
                            results = this.StreamingEvaluate(context, pattern + 1, out halt);

                            //If recursion leads to a halt then we halt and return immediately
                            if (halt && results.Count >= this._requiredResults && this._requiredResults != -1)
                            {
                                return results;
                            }
                            else if (halt)
                            {
                                if (results.Count == 0)
                                {
                                    //If recursing leads to no results then eliminate all outputs
                                    //Also reset to prevResults to -1
                                    resultsFound = 0;
                                    localOutput = new Multiset();
                                    prevResults = -1;
                                }
                                else if (prevResults > -1)
                                {
                                    if (results.Count == prevResults)
                                    {
                                        //If the amount of results found hasn't increased then this match does not
                                        //generate any further solutions further down the recursion so we can eliminate
                                        //this from the results
                                        localOutput.Remove(localOutput.SetIDs.Max());
                                    }
                                }
                                prevResults = results.Count;

                                //If we're supposed to halt but not reached the number of required results then continue
                                context.InputMultiset = initialInput;
                                context.OutputMultiset = localOutput;
                            }
                            else
                            {
                                //Otherwise we need to keep going here
                                //So must reset our input and outputs before continuing
                                context.InputMultiset = initialInput;
                                context.OutputMultiset = new Multiset();
                                resultsFound--;
                            }
                        }
                        else
                        {
                            //If we're at the last pattern and we've found a match then we can halt
                            halt = true;

                            //Generate the final output and return it
                            if (context.InputMultiset.IsDisjointWith(context.OutputMultiset))
                            {
                                //Disjoint so do a Product
                                results = context.InputMultiset.ProductWithTimeout(context.OutputMultiset, context.RemainingTimeout);
                            }
                            else
                            {
                                //Normal Join
                                results = context.InputMultiset.Join(context.OutputMultiset);
                            }

                            //If not reached required number of results continue
                            if (results.Count >= this._requiredResults && this._requiredResults != -1)
                            {
                                context.OutputMultiset = results;
                                return context.OutputMultiset;
                            }
                        }
                    }
                }
            }
            else if (temp is FilterPattern)
            {
                FilterPattern filter = (FilterPattern)temp;
                ISparqlExpression filterExpr = filter.Filter.Expression;

                if (filter.Variables.IsDisjoint(context.InputMultiset.Variables))
                {
                    //Remember to check for Timeouts during Lazy Evaluation
                    context.CheckTimeout();

                    //Filter is Disjoint so determine whether it has any affect or not
                    if (filter.Variables.Any())
                    {
                        //Has Variables but disjoint from input => not in scope so gets ignored

                        //Do we recurse or not?
                        if (pattern < this._triplePatterns.Count - 1)
                        {
                            //Recurse and return
                            results = this.StreamingEvaluate(context, pattern + 1, out halt);
                            return results;
                        }
                        else
                        {
                            //We don't affect the input in any way so just return it
                            return context.InputMultiset;
                        }
                    }
                    else
                    {
                        //No Variables so have to evaluate it to see if it gives true otherwise
                        try
                        {
                            if (filterExpr.Evaluate(context, 0).AsSafeBoolean())
                            {
                                if (pattern < this._triplePatterns.Count - 1)
                                {
                                    //Recurse and return
                                    results = this.StreamingEvaluate(context, pattern + 1, out halt);
                                    return results;
                                }
                                else
                                {
                                    //Last Pattern and we evaluate to true so can return the input as-is
                                    halt = true;
                                    return context.InputMultiset;
                                }
                            }
                        }
                        catch (RdfQueryException)
                        {
                            //Evaluates to false so eliminates all solutions (use an empty Multiset)
                            return new Multiset();
                        }
                    }
                }
                else
                {
                    //Remember to check for Timeouts during Lazy Evaluation
                    context.CheckTimeout();

                    //Test each solution found so far against the Filter and eliminate those that evalute to false/error
                    foreach (int id in context.InputMultiset.SetIDs.ToList())
                    {
                        try
                        {
                            if (filterExpr.Evaluate(context, id).AsSafeBoolean())
                            {
                                //If evaluates to true then add to output
                                context.OutputMultiset.Add(context.InputMultiset[id].Copy());
                            }
                        }
                        catch (RdfQueryException)
                        {
                            //Error means we ignore the solution
                        }
                    }

                    //Remember to check for Timeouts during Lazy Evaluation
                    context.CheckTimeout();

                    //Decide whether to recurse or not
                    resultsFound = context.OutputMultiset.Count;
                    if (pattern < this._triplePatterns.Count - 1)
                    {
                        //Recurse then return
                        //We can never decide whether to recurse again at this point as we are not capable of deciding
                        //which solutions should be dumped (that is the job of an earlier pattern in the BGP)
                        results = this.StreamingEvaluate(context, pattern + 1, out halt);

                        return results;
                    }
                    else
                    {
                        halt = true;

                        //However many results we need we'll halt - previous patterns can call us again if they find more potential solutions
                        //for us to filter
                        return context.OutputMultiset;
                    }
                }
            }
            else if (temp is BindPattern)
            {
                BindPattern bind = (BindPattern)temp;
                ISparqlExpression bindExpr = bind.AssignExpression;
                String bindVar = bind.VariableName;

                if (context.InputMultiset.ContainsVariable(bindVar))
                {
                    throw new RdfQueryException("Cannot use a BIND assigment to BIND to a variable that has previously been used in the Query");
                }
                else
                {
                    //Remember to check for Timeouts during Lazy Evaluation
                    context.CheckTimeout();

                    //Compute the Binding for every value
                    context.OutputMultiset.AddVariable(bindVar);
                    foreach (ISet s in context.InputMultiset.Sets)
                    {
                        ISet x = s.Copy();
                        try
                        {
                            INode val = bindExpr.Evaluate(context, s.ID);
                            x.Add(bindVar, val);
                        }
                        catch (RdfQueryException)
                        {
                            //Equivalent to no assignment but the solution is preserved
                        }
                        context.OutputMultiset.Add(x.Copy());
                    }

                    //Remember to check for Timeouts during Lazy Evaluation
                    context.CheckTimeout();

                    //Decide whether to recurse or not
                    resultsFound = context.OutputMultiset.Count;
                    if (pattern < this._triplePatterns.Count - 1)
                    {
                        //Recurse then return
                        results = this.StreamingEvaluate(context, pattern + 1, out halt);
                        return results;
                    }
                    else
                    {
                        halt = true;

                        //However many results we need we'll halt - previous patterns can call us again if they find more potential solutions
                        //for us to extend
                        return context.OutputMultiset;
                    }
                }
            }
            else
            {
                throw new RdfQueryException("Encountered a " + temp.GetType().FullName + " which is not a lazily evaluable Pattern");
            }

            //If we found no possibles we return the null multiset
            if (resultsFound == 0)
            {
                return new NullMultiset();
            }
            else
            {
                //Generate the final output and return it
                if (!modifies)
                {
                    if (context.InputMultiset.IsDisjointWith(context.OutputMultiset))
                    {
                        //Disjoint so do a Product
                        results = context.InputMultiset.ProductWithTimeout(context.OutputMultiset, context.RemainingTimeout);
                    }
                    else
                    {
                        //Normal Join
                        results = context.InputMultiset.Join(context.OutputMultiset);
                    }
                    context.OutputMultiset = results;
                }
                return context.OutputMultiset;
            }
        }