Beispiel #1
0
 /// <summary>
 /// Creates a new Multiset by flattening a Group Multiset
 /// </summary>
 /// <param name="multiset">Group Multiset</param>
 internal Multiset(GroupMultiset multiset)
 {
     foreach (String var in multiset.Variables)
     {
         this.AddVariable(var);
     }
     foreach (ISet s in multiset.Sets)
     {
         this.Add(s.Copy());
     }
 }
Beispiel #2
0
        /// <summary>
        /// Applies the Projection to the results of Evaluating the Inner Pattern
        /// </summary>
        /// <param name="context">Evaluation Context</param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            try
            {
                context.InputMultiset = context.Evaluate(this._pattern);//this._pattern.Evaluate(context);
            }
            catch (RdfQueryTimeoutException)
            {
                //If not partial results throw the error
                if (!context.Query.PartialResultsOnTimeout)
                {
                    throw;
                }
            }

            IEnumerable <SparqlVariable> vars;

            if (context.Query != null)
            {
                vars = context.Query.Variables;
            }
            else
            {
                vars = this._variables;
            }

            //For Null and Identity Multisets this is just a simple selection
            if (context.InputMultiset is NullMultiset)
            {
                context.InputMultiset  = new Multiset(vars.Select(v => v.Name));
                context.OutputMultiset = context.InputMultiset;
            }
            else if (context.InputMultiset is IdentityMultiset)
            {
                context.InputMultiset = new Multiset(vars.Select(v => v.Name));
                Set s = new Set();
                context.InputMultiset.Add(s);
                context.OutputMultiset = context.InputMultiset;
            }

            //If we have a Group Multiset then Projection is more complex
            GroupMultiset groupSet = null;

            if (context.InputMultiset is GroupMultiset)
            {
                groupSet = (GroupMultiset)context.InputMultiset;

                //Project all simple variables for the Groups here
                foreach (SparqlVariable v in vars.Where(v => v.IsResultVariable && !v.IsProjection && !v.IsAggregate))
                {
                    //Can only project a variable if it's used in the GROUP OR if it was assigned by a GROUP BY expression
                    if (context.Query != null)
                    {
                        if (!groupSet.ContainsVariable(v.Name) && !context.Query.GroupBy.Variables.Contains(v.Name) && !context.Query.GroupBy.ProjectableVariables.Contains(v.Name))
                        {
                            throw new RdfQueryException("Cannot project the variable ?" + v.Name + " since this Query contains Grouping(s) but the given Variable is not in the GROUP BY - use the SAMPLE aggregate if you need to sample this Variable");
                        }
                    }

                    //Project the value for each variable
                    if (!groupSet.ContainsVariable(v.Name))
                    {
                        //Simple Variable Projection used in GROUP BY so grab first value as all should be same
                        //for the group
                        context.OutputMultiset.AddVariable(v.Name);
                        foreach (int id in groupSet.SetIDs)
                        {
                            INode value = groupSet.Contents[groupSet.GroupSetIDs(id).First()][v.Name];
                            context.OutputMultiset[id].Add(v.Name, value);
                        }
                    }
                }
            }
            else if (context.Query != null && context.Query.IsAggregate)
            {
                context.OutputMultiset = new Multiset();
            }

            //Project the rest of the Variables
            Set aggSet = new Set();

            foreach (SparqlVariable v in vars.Where(v => v.IsResultVariable))
            {
                if (groupSet == null)
                {
                    context.InputMultiset.AddVariable(v.Name);
                }
                else
                {
                    context.OutputMultiset.AddVariable(v.Name);
                }

                if (v.IsAggregate)
                {
                    //Compute the Aggregate
                    if (groupSet != null)
                    {
                        context.InputMultiset = groupSet.Contents;
                        foreach (int id in groupSet.SetIDs)
                        {
                            INode aggValue = v.Aggregate.Apply(context, groupSet.GroupSetIDs(id));
                            context.OutputMultiset[id].Add(v.Name, aggValue);
                        }
                        context.InputMultiset = groupSet;
                    }
                    else
                    {
                        INode aggValue = v.Aggregate.Apply(context, context.InputMultiset.SetIDs);
                        aggSet.Add(v.Name, aggValue);
                    }
                }
                else if (v.IsProjection)
                {
                    if (context.Query != null && context.Query.IsAggregate && context.Query.GroupBy == null)
                    {
                        throw new RdfQueryException("Cannot project an expression since this Query contains Aggregates and no GROUP BY");
                    }
                    else
                    {
                        //Compute the Value of the Projection Expression for each Set
                        foreach (int id in context.InputMultiset.SetIDs)
                        {
                            ISet s = context.InputMultiset[id];
                            try
                            {
                                INode temp = v.Projection.Evaluate(context, id);
                                s.Add(v.Name, temp);
                            }
                            catch (RdfQueryException)
                            {
                                s.Add(v.Name, null);
                            }
                        }
                    }
                }
                else
                {
                    if (context.Query != null && context.Query.IsAggregate && context.Query.GroupBy == null)
                    {
                        //If this is an Aggregate without a GROUP BY projected variables are invalid
                        throw new RdfQueryException("Cannot project the variable ?" + v.Name + " since this Query contains Aggregates and no GROUP BY");
                    }
                    else if (context.Query != null && context.Query.IsAggregate && !context.Query.GroupBy.ProjectableVariables.Contains(v.Name))
                    {
                        //If this is an Aggregate with a GROUP BY projected variables are only valid if they occur in the GROUP BY
                        throw new RdfQueryException("Cannot project the variable ?" + v.Name + " since this Query contains Aggregates but the given Variable is not in the GROUP BY - use the SAMPLE aggregate if you need to access this variable");
                    }

                    //Otherwise we don't need to do anything with the Variable
                }
            }

            if (context.Query != null && context.Query.IsAggregate && context.Query.GroupBy == null)
            {
                context.OutputMultiset.Add(aggSet);
            }
            else
            {
                context.OutputMultiset = context.InputMultiset;
            }

            return(context.OutputMultiset);
        }
Beispiel #3
0
        /// <summary>
        /// Evaluates a Group By by generating a <see cref="GroupMultiset">GroupMultiset</see> from the Input Multiset
        /// </summary>
        /// <param name="context">SPARQL Evaluation Context</param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            BaseMultiset results = context.Evaluate(this._pattern);

            context.InputMultiset = results;

            //Identity/Null yields an empty multiset
            if (context.InputMultiset is IdentityMultiset || context.InputMultiset is NullMultiset)
            {
                results = new Multiset();
            }
            GroupMultiset       groupSet = new GroupMultiset(results);
            List <BindingGroup> groups;

            //Calculate Groups
            if (context.Query.GroupBy != null)
            {
                groups = context.Query.GroupBy.Apply(context);
            }
            else if (this._grouping != null)
            {
                groups = this._grouping.Apply(context);
            }
            else
            {
                groups = new List <BindingGroup>()
                {
                    new BindingGroup(results.SetIDs)
                };
            }

            //Add Groups to the GroupMultiset
            HashSet <String> vars = new HashSet <String>();

            foreach (BindingGroup group in groups)
            {
                foreach (KeyValuePair <String, INode> assignment in group.Assignments)
                {
                    if (vars.Contains(assignment.Key))
                    {
                        continue;
                    }

                    groupSet.AddVariable(assignment.Key);
                    vars.Add(assignment.Key);
                }
                groupSet.AddGroup(group);
            }
            //If grouping produced no groups and there are aggregates present
            //then an implicit group is created
            if (groups.Count == 0 && this._aggregates.Count > 0)
            {
                groupSet.AddGroup(new BindingGroup());
            }

            //Apply the aggregates
            context.InputMultiset = groupSet;
            context.Binder.SetGroupContext(true);
            foreach (SparqlVariable var in this._aggregates)
            {
                if (!vars.Contains(var.Name))
                {
                    groupSet.AddVariable(var.Name);
                    vars.Add(var.Name);
                }

                foreach (ISet s in groupSet.Sets)
                {
                    try
                    {
                        INode value = var.Aggregate.Apply(context, groupSet.GroupSetIDs(s.ID));
                        s.Add(var.Name, value);
                    }
                    catch (RdfQueryException)
                    {
                        s.Add(var.Name, null);
                    }
                }
            }
            context.Binder.SetGroupContext(false);

            context.OutputMultiset = groupSet;
            return(context.OutputMultiset);
        }
Beispiel #4
0
 /// <summary>
 /// Creates a new Multiset by flattening a Group Multiset
 /// </summary>
 /// <param name="multiset">Group Multiset</param>
 internal Multiset(GroupMultiset multiset)
 {
     foreach (String var in multiset.Variables)
     {
         this.AddVariable(var);
     }
     foreach (ISet s in multiset.Sets)
     {
         this.Add(s.Copy());
     }
 }
 /// <summary>
 /// Sets the Group Context for the Binder
 /// </summary>
 /// <param name="accessContents">Whether you want to access the Group Contents or the Groups themselves</param>
 public override void SetGroupContext(bool accessContents)
 {
     if (accessContents)
     {
         if (this._context.InputMultiset is GroupMultiset)
         {
             this._groupSet = (GroupMultiset)this._context.InputMultiset;
             this._context.InputMultiset = this._groupSet.Contents;
         }
         else
         {
             throw new RdfQueryException("Cannot set Group Context to access Contents data when the Input is not a Group Multiset");
         }
     }
     else
     {
         if (this._groupSet != null)
         {
             this._context.InputMultiset = this._groupSet;
             this._groupSet = null;
         }
         else
         {
             throw new RdfQueryException("Cannot set Group Context to acess Group data when there is no Group data available");
         }
     }
 }