Ejemplo n.º 1
0
 /// <summary>
 /// Creates a new Filter Pattern with the given Filter
 /// </summary>
 /// <param name="filter">Filter</param>
 public FilterPattern(ISparqlFilter filter)
 {
     this._filter = filter;
     this._indexType = TripleIndexType.SpecialFilter;
     this._vars = filter.Variables.Distinct().ToList();
     this._vars.Sort();
 }
Ejemplo n.º 2
0
        /// <summary>
        /// Creates a new Graph Pattern copied from an existing Graph Pattern
        /// </summary>
        /// <param name="gp">Graph Pattern</param>
        internal GraphPattern(GraphPattern gp)
        {
            _break  = gp._break;
            _broken = gp._broken;
            _filter = gp._filter;
            _graphPatterns.AddRange(gp._graphPatterns);
            _graphSpecifier = gp._graphSpecifier;
            _isExists       = gp._isExists;
            _isFiltered     = gp._isFiltered;
            _isGraph        = gp._isGraph;
            _isMinus        = gp._isMinus;
            _isNotExists    = gp._isExists;
            _isOptional     = gp._isOptional;
            _isService      = gp._isService;
            _isSilent       = gp._isSilent;
            _isUnion        = gp._isUnion;

            // Copy Triple Patterns across
            // Assignments and Filters are copied into the unplaced lists so the new pattern can be reoptimised if it gets modified since
            // reoptimising a pattern with already placed filters and assignments can lead to strange results
            _triplePatterns.AddRange(gp._triplePatterns.Where(tp => tp.PatternType != TriplePatternType.BindAssignment && tp.PatternType != TriplePatternType.LetAssignment && tp.PatternType != TriplePatternType.Filter));
            _unplacedAssignments.AddRange(gp._unplacedAssignments);
            _unplacedAssignments.AddRange(gp._triplePatterns.Where(tp => tp.PatternType == TriplePatternType.BindAssignment || tp.PatternType == TriplePatternType.LetAssignment).OfType <IAssignmentPattern>());
            _unplacedFilters.AddRange(gp._unplacedFilters);
            _unplacedFilters.AddRange(gp._triplePatterns.Where(tp => tp.PatternType == TriplePatternType.Filter).OfType <IFilterPattern>().Select(fp => fp.Filter));
        }
Ejemplo n.º 3
0
 /// <summary>
 /// Creates a new Filter Pattern with the given Filter
 /// </summary>
 /// <param name="filter">Filter</param>
 public FilterPattern(ISparqlFilter filter)
 {
     this._filter    = filter;
     this._indexType = TripleIndexType.SpecialFilter;
     this._vars      = filter.Variables.Distinct().ToList();
     this._vars.Sort();
 }
Ejemplo n.º 4
0
        /// <summary>
        /// Inserts a Filter at a given position
        /// </summary>
        /// <param name="filter">Filter</param>
        /// <param name="i">Position to insert at</param>
        /// <remarks>
        /// Intended for use by Query Optimisers
        /// </remarks>
        public void InsertFilter(ISparqlFilter filter, int i)
        {
            if (!_unplacedFilters.Contains(filter))
            {
                throw new RdfQueryException("Cannot Insert a Filter that is not currentlyy an unplaced Filter in this Graph Pattern");
            }
            _unplacedFilters.Remove(filter);
            FilterPattern p = new FilterPattern(filter);

            _triplePatterns.Insert(i, p);
        }
Ejemplo n.º 5
0
 internal GraphPattern(GraphPattern gp)
 {
     this._break  = gp._break;
     this._broken = gp._broken;
     this._filter = gp._filter;
     this._graphPatterns.AddRange(gp._graphPatterns);
     this._graphSpecifier = gp._graphSpecifier;
     this._isExists       = gp._isExists;
     this._isFiltered     = gp._isFiltered;
     this._isGraph        = gp._isGraph;
     this._isMinus        = gp._isMinus;
     this._isNotExists    = gp._isExists;
     this._isOptimised    = gp._isOptimised;
     this._isOptional     = gp._isOptional;
     this._isService      = gp._isService;
     this._isSilent       = gp._isSilent;
     this._isUnion        = gp._isUnion;
     this._triplePatterns.AddRange(gp._triplePatterns);
     this._unplacedAssignments.AddRange(gp._unplacedAssignments);
     this._unplacedFilters.AddRange(gp._unplacedFilters);
 }
Ejemplo n.º 6
0
 internal GraphPattern(GraphPattern gp)
 {
     this._break = gp._break;
     this._broken = gp._broken;
     this._filter = gp._filter;
     this._graphPatterns.AddRange(gp._graphPatterns);
     this._graphSpecifier = gp._graphSpecifier;
     this._isExists = gp._isExists;
     this._isFiltered = gp._isFiltered;
     this._isGraph = gp._isGraph;
     this._isMinus = gp._isMinus;
     this._isNotExists = gp._isExists;
     this._isOptimised = gp._isOptimised;
     this._isOptional = gp._isOptional;
     this._isService = gp._isService;
     this._isSilent = gp._isSilent;
     this._isUnion = gp._isUnion;
     this._triplePatterns.AddRange(gp._triplePatterns);
     this._unplacedAssignments.AddRange(gp._unplacedAssignments);
     this._unplacedFilters.AddRange(gp._unplacedFilters);
 }
Ejemplo n.º 7
0
        /// <summary>
        /// Tries to place filters at the earliest point possible i.e. the first point after which all required variables have occurred
        /// </summary>
        /// <param name="gp">Graph Pattern</param>
        /// <param name="filter">Filter to place</param>
        /// <returns></returns>
        private bool TryPlaceFilter(GraphPattern gp, ISparqlFilter filter)
        {
            // Firstly we need to find out what variables are needed in the Filter
            List <String> variablesNeeded = filter.Variables.Distinct().ToList();

            // Then we need to move through the Triple Patterns and find the first place at which all the
            // Variables used in the Filter have been used in ordinary Triple Patterns
            List <String> variablesUsed = new List <string>();

            for (int p = 0; p < gp.TriplePatterns.Count; p++)
            {
                if (gp.TriplePatterns[p].PatternType == TriplePatternType.Match || gp.TriplePatterns[p].PatternType == TriplePatternType.BindAssignment || gp.TriplePatterns[p].PatternType == TriplePatternType.LetAssignment)
                {
                    foreach (String var in gp.TriplePatterns[p].Variables)
                    {
                        if (!variablesUsed.Contains(var))
                        {
                            variablesUsed.Add(var);
                        }
                    }

                    // Have all the Variables we need now been used in a Pattern?
                    if (variablesNeeded.All(v => variablesUsed.Contains(v)))
                    {
                        // We can place this Filter after the Pattern we were just looking at
                        gp.InsertFilter(filter, p + 1);
                        return(true);
                    }
                }
            }

            // If we reach here then this means that all the Variables used in the Filter did not occur
            // in the Triple Patterns which means they likely occur in child graph patterns (or the query
            // is malformed).  In this case we cannot place the Filter and it has to be applied post-commit
            // rather than during Triple Pattern execution
            return(false);
        }
Ejemplo n.º 8
0
 /// <summary>
 /// Creates a new LeftJoin where there is a Filter over the join
 /// </summary>
 /// <param name="lhs">LHS Pattern</param>
 /// <param name="rhs">RHS Pattern</param>
 /// <param name="filter">Filter to decide which RHS solutions are valid</param>
 public LeftJoin(ISparqlAlgebra lhs, ISparqlAlgebra rhs, ISparqlFilter filter)
 {
     this._lhs = lhs;
     this._rhs = rhs;
     this._filter = filter;
 }
Ejemplo n.º 9
0
 /// <summary>
 /// Adds a Filter to the Graph Pattern
 /// </summary>
 /// <param name="filter">Filter</param>
 internal void AddFilter(ISparqlFilter filter)
 {
     _isFiltered = true;
     _unplacedFilters.Add(filter);
 }
Ejemplo n.º 10
0
 /// <summary>
 /// Creates a new Single Value Restriction Filter
 /// </summary>
 /// <param name="pattern">Algebra the filter applies over</param>
 /// <param name="var">Variable to restrict on</param>
 /// <param name="term">Value to restrict to</param>
 /// <param name="filter">Filter to use</param>
 public SingleValueRestrictionFilter(ISparqlAlgebra pattern, String var, ConstantTerm term, ISparqlFilter filter)
     : base(pattern, var, filter)
 {
     this._term = term;
 }
Ejemplo n.º 11
0
 /// <summary>
 /// Creates a new Single Value Restriction Filter
 /// </summary>
 /// <param name="pattern">Algebra the filter applies over</param>
 /// <param name="var">Variable to restrict on</param>
 /// <param name="term">Value to restrict to</param>
 /// <param name="filter">Filter to use</param>
 public SingleValueRestrictionFilter(ISparqlAlgebra pattern, String var, NodeExpressionTerm term, ISparqlFilter filter)
     : base(pattern, var, filter)
 {
     this._term = term;
 }
Ejemplo n.º 12
0
 /// <summary>
 /// Creates a new Single Value Restriction Filter.
 /// </summary>
 /// <param name="pattern">Algebra the filter applies over.</param>
 /// <param name="var">Variable to restrict on.</param>
 /// <param name="term">Value to restrict to.</param>
 /// <param name="filter">Filter to use.</param>
 public SingleValueRestrictionFilter(ISparqlAlgebra pattern, String var, ConstantTerm term, ISparqlFilter filter)
     : base(pattern, var, filter)
 {
     _term = term;
 }
Ejemplo n.º 13
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");
        }
Ejemplo n.º 14
0
 /// <summary>
 /// Adds an additional Filter to the Filter Chain
 /// </summary>
 /// <param name="filter">A Filter to add</param>
 protected internal void Add(ISparqlFilter filter)
 {
     this._filters.Add(filter);
 }
Ejemplo n.º 15
0
 /// <summary>
 /// Creates a new Filter
 /// </summary>
 /// <param name="pattern">Algebra the Filter applies over</param>
 /// <param name="filter">Filter to apply</param>
 public Filter(ISparqlAlgebra pattern, ISparqlFilter filter)
 {
     this._pattern = pattern;
     this._filter = filter;
 }
Ejemplo n.º 16
0
 /// <summary>
 /// Creates a new Chain Filter
 /// </summary>
 /// <param name="first">First Filter</param>
 /// <param name="second">Second Filter</param>
 public ChainFilter(ISparqlFilter first, ISparqlFilter second)
 {
     this._filters.Add(first);
     this._filters.Add(second);
 }
Ejemplo n.º 17
0
 /// <summary>
 /// Creates a new Chain Filter
 /// </summary>
 /// <param name="first">First Filter</param>
 /// <param name="rest">Additional Filters</param>
 public ChainFilter(ISparqlFilter first, IEnumerable<ISparqlFilter> rest)
 {
     this._filters.Add(first);
     this._filters.AddRange(rest);
 }
Ejemplo n.º 18
0
 /// <summary>
 /// Creates a new Filter
 /// </summary>
 /// <param name="pattern">Algebra the Filter applies over</param>
 /// <param name="filter">Filter to apply</param>
 public Filter(ISparqlAlgebra pattern, ISparqlFilter filter)
 {
     _pattern = pattern;
     _filter  = filter;
 }
Ejemplo n.º 19
0
 /// <summary>
 /// Creates a new Filter Pattern with the given Filter
 /// </summary>
 /// <param name="filter">Filter</param>
 public FilterPattern(ISparqlFilter filter)
 {
     this._filter = filter;
     this._vars   = filter.Variables.Distinct().ToList();
     this._vars.Sort();
 }
Ejemplo n.º 20
0
 /// <summary>
 /// Creates a new Variable Restriction Filter
 /// </summary>
 /// <param name="pattern">Algebra the filter applies over</param>
 /// <param name="var">Variable to restrict on</param>
 /// <param name="filter">Filter to use</param>
 public VariableRestrictionFilter(ISparqlAlgebra pattern, String var, ISparqlFilter filter)
 {
     this._pattern = pattern;
     this._var = var;
     this._filter = filter;
 }
Ejemplo n.º 21
0
 /// <summary>
 /// Adds a Filter to the Graph Pattern respecting any BGP breaks
 /// </summary>
 /// <param name="filter">Filter</param>
 internal void AddFilter(ISparqlFilter filter)
 {
     this._unplacedFilters.Add(filter);
 }
Ejemplo n.º 22
0
 /// <summary>
 /// Creates a new Chain Filter
 /// </summary>
 /// <param name="first">First Filter</param>
 /// <param name="second">Second Filter</param>
 public ChainFilter(ISparqlFilter first, ISparqlFilter second)
 {
     _filters.Add(first);
     _filters.Add(second);
 }
Ejemplo n.º 23
0
 /// <summary>
 /// Creates a new LeftJoin where there is a Filter over the join
 /// </summary>
 /// <param name="lhs">LHS Pattern</param>
 /// <param name="rhs">RHS Pattern</param>
 /// <param name="filter">Filter to decide which RHS solutions are valid</param>
 public LeftJoin(ISparqlAlgebra lhs, ISparqlAlgebra rhs, ISparqlFilter filter)
 {
     this._lhs    = lhs;
     this._rhs    = rhs;
     this._filter = filter;
 }
Ejemplo n.º 24
0
 /// <summary>
 /// Adds an additional Filter to the Filter Chain
 /// </summary>
 /// <param name="filter">A Filter to add</param>
 protected internal void Add(ISparqlFilter filter)
 {
     _filters.Add(filter);
 }
Ejemplo n.º 25
0
 /// <summary>
 /// Creates a new Filter
 /// </summary>
 /// <param name="pattern">Algebra the Filter applies over</param>
 /// <param name="filter">Filter to apply</param>
 public Filter(ISparqlAlgebra pattern, ISparqlFilter filter)
 {
     this._pattern = pattern;
     this._filter  = filter;
 }
Ejemplo n.º 26
0
 /// <summary>
 /// Adds a Filter to the Graph Pattern respecting any BGP breaks
 /// </summary>
 /// <param name="filter">Filter</param>
 internal void AddFilter(ISparqlFilter filter)
 {
     this._unplacedFilters.Add(filter);
 }
Ejemplo n.º 27
0
 /// <summary>
 /// Creates a new Variable Restriction Filter.
 /// </summary>
 /// <param name="pattern">Algebra the filter applies over.</param>
 /// <param name="var">Variable to restrict on.</param>
 /// <param name="filter">Filter to use.</param>
 public VariableRestrictionFilter(ISparqlAlgebra pattern, String var, ISparqlFilter filter)
 {
     _pattern = pattern;
     _var     = var;
     _filter  = filter;
 }
Ejemplo n.º 28
0
 /// <summary>
 /// Creates a new Having Clause
 /// </summary>
 /// <param name="pattern">Pattern</param>
 /// <param name="having">Having Clause</param>
 public Having(ISparqlAlgebra pattern, ISparqlFilter having)
 {
     this._pattern = pattern;
     this._having  = having;
 }
Ejemplo n.º 29
0
        /// <summary>
        /// Tries to place filters at the earliest point possible i.e. the first point after which all required variables have occurred
        /// </summary>
        /// <param name="gp">Graph Pattern</param>
        /// <param name="filter">Filter to place</param>
        /// <returns></returns>
        private bool TryPlaceFilter(GraphPattern gp, ISparqlFilter filter)
        {
            //Firstly we need to find out what variables are needed in the Filter
            List<String> variablesNeeded = filter.Variables.Distinct().ToList();

            //Then we need to move through the Triple Patterns and find the first place at which all the
            //Variables used in the Filter have been used in ordinary Triple Patterns
            List<String> variablesUsed = new List<string>();
            for (int p = 0; p < gp.TriplePatterns.Count; p++)
            {
                if (gp.TriplePatterns[p] is TriplePattern || gp.TriplePatterns[p] is IAssignmentPattern)
                {
                    foreach (String var in gp.TriplePatterns[p].Variables)
                    {
                        if (!variablesUsed.Contains(var)) variablesUsed.Add(var);
                    }

                    //Have all the Variables we need now been used in a Pattern?
                    if (variablesNeeded.All(v => variablesUsed.Contains(v)))
                    {
                        //We can place this Filter after the Pattern we were just looking at
                        gp.InsertFilter(filter, p + 1);
                        return true;
                    }
                }
            }

            //If we reach here then this means that all the Variables used in the Filter did not occur
            //in the Triple Patterns which means they likely occur in child graph patterns (or the query
            //is malformed).  In this case we cannot place the Filter and it has to be applied post-commit
            //rather than during Triple Pattern execution
            return false;
        }
Ejemplo n.º 30
0
 /// <summary>
 /// Inserts a Filter at a given position
 /// </summary>
 /// <param name="filter">Filter</param>
 /// <param name="i">Position to insert at</param>
 /// <remarks>
 /// Intended for use by Query Optimisers
 /// </remarks>
 public void InsertFilter(ISparqlFilter filter, int i)
 {
     if (!this._unplacedFilters.Contains(filter)) throw new RdfQueryException("Cannot Insert a Filter that is not currentlyy an unplaced Filter in this Graph Pattern");
     this._unplacedFilters.Remove(filter);
     FilterPattern p = new FilterPattern(filter);
     this._triplePatterns.Insert(i, p);
 }
Ejemplo n.º 31
0
 /// <summary>
 /// Creates a new Chain Filter
 /// </summary>
 /// <param name="first">First Filter</param>
 /// <param name="rest">Additional Filters</param>
 public ChainFilter(ISparqlFilter first, IEnumerable <ISparqlFilter> rest)
 {
     _filters.Add(first);
     _filters.AddRange(rest);
 }
Ejemplo n.º 32
0
        /// <summary>
        /// Causes the Graph Pattern to be optimised if it isn't already
        /// </summary>
        /// <param name="gp">Graph Pattern</param>
        /// <param name="variables">Variables that have occurred prior to this Pattern</param>
        public void Optimise(GraphPattern gp, IEnumerable <String> variables)
        {
            // Our Variables is initially only those in our Triple Patterns since
            // anything else is considered to be out of scope
            List <String> ourVariables = (from tp in gp.TriplePatterns
                                          from v in tp.Variables
                                          select v).Distinct().ToList();

            // Start by sorting the Triple Patterns in the list according to the ranking function
            gp.TriplePatterns.Sort(GetRankingComparer());

            // Apply reordering unless an optimiser has chosen to disable it
            if (ShouldReorder)
            {
                if (gp.TriplePatterns.Count > 0)
                {
                    // After we sort which gives us a rough optimisation we then may want to reorder
                    // based on the Variables that occurred previous to us OR if we're the Root Graph Pattern

                    if (!variables.Any())
                    {
                        // Optimise this Graph Pattern
                        // No previously occurring variables so must be the first Graph Pattern
                        if (gp.TriplePatterns.Count > 1)
                        {
                            HashSet <String> currVariables = new HashSet <String>();
                            gp.TriplePatterns[0].Variables.ForEach(v => currVariables.Add(v));
                            for (int i = 1; i < gp.TriplePatterns.Count - 1; i++)
                            {
                                if (currVariables.Count == 0)
                                {
                                    gp.TriplePatterns[i].Variables.ForEach(v => currVariables.Add(v));
                                    continue;
                                }
                                else if (currVariables.IsDisjoint(gp.TriplePatterns[i].Variables))
                                {
                                    TryReorderPatterns(gp, currVariables.ToList(), i + 1, i);
                                    gp.TriplePatterns[i].Variables.ForEach(v => currVariables.Add(v));
                                }
                                else
                                {
                                    gp.TriplePatterns[i].Variables.ForEach(v => currVariables.Add(v));
                                }
                            }
                        }
                    }
                    else
                    {
                        // Optimise this Graph Pattern based on previously occurring variables
                        if (gp.TriplePatterns.Count > 1 && !gp.TriplePatterns[0].Variables.Any(v => variables.Contains(v)) && variables.Intersect(ourVariables).Any())
                        {
                            TryReorderPatterns(gp, variables.ToList(), 1, 0);
                        }
                        else if (gp.TriplePatterns.Count > 2)
                        {
                            // In the case where there are more than 2 patterns then we can try and reorder these
                            // in order to further optimise the pattern
                            TryReorderPatterns(gp, gp.TriplePatterns[0].Variables, 2, 1);
                        }
                    }
                }
            }

            if (ShouldPlaceAssignments)
            {
                // First we need to place Assignments (LETs) in appropriate places within the Pattern
                // This happens before Filter placement since Filters may use variables assigned to in LETs
                if (gp.UnplacedAssignments.Any())
                {
                    // Need to ensure that we sort Assignments
                    // This way those that use fewer variables get placed first
                    List <IAssignmentPattern> ps = gp.UnplacedAssignments.OrderBy(x => x).ToList();

                    // This next bit goes in a do loop as we want to keep attempting to place assignments while
                    // we are able to do so.  If the count of unplaced assignments has decreased but is not
                    // zero it may be that we were unable to place some patterns as they relied on variables
                    // assigned in other LETs which weren't placed when we attempted to place them
                    // When we reach the point where no further placements have occurred or all assignments
                    // are placed we stop trying to place assignments
                    int c;
                    do
                    {
                        c = ps.Count;

                        int i = 0;
                        while (i < ps.Count)
                        {
                            if (TryPlaceAssignment(gp, ps[i]))
                            {
                                // Remove from Unplaced Assignments since it's been successfully placed in the Triple Patterns
                                // Don't increment the counter since the next Assignment is now at the index we're already at
                                ps.RemoveAt(i);
                            }
                            else
                            {
                                // Unable to place so increment counter
                                i++;
                            }
                        }
                    } while (c > ps.Count && ps.Count > 0);
                }
            }

            // Regardless of what we've placed already we now place all remaining assignments
            // foreach (IAssignmentPattern assignment in gp.UnplacedAssignments.ToList())
            // {
            //    gp.InsertAssignment(assignment, gp.TriplePatterns.Count);
            // }


            if (ShouldPlaceFilters)
            {
                // Then we need to place the Filters in appropriate places within the Pattern
                if (gp.UnplacedFilters.Any())
                {
                    if (gp.TriplePatterns.Count == 0)
                    {
                        // Where there are no Triple Patterns the Graph Pattern just contains this Filter and possibly some
                        // child Graph Patterns.  In such a case then we shouldn't place the Filters
                    }
                    else
                    {
                        if (ShouldSplitFilters)
                        {
                            // See whether we can split any/all of the Unplaced Filters
                            List <ISparqlFilter> fs = gp.UnplacedFilters.ToList();
                            for (int i = 0; i < fs.Count; i++)
                            {
                                ISparqlFilter f = fs[i];
                                if (f.Expression is AndExpression)
                                {
                                    // Split the And
                                    // Note that multiple nested And's are handled by the fact that we will continue working through the list until it is finished
                                    UnaryExpressionFilter lhs = new UnaryExpressionFilter(f.Expression.Arguments.First());
                                    UnaryExpressionFilter rhs = new UnaryExpressionFilter(f.Expression.Arguments.Last());
                                    fs.RemoveAt(i);
                                    fs.Add(lhs);
                                    fs.Add(rhs);
                                }
                            }
                            // Finally we need to ensure the Unplaced Filters list is appropriately updated
                            gp.ResetFilters(fs);
                        }

                        foreach (ISparqlFilter f in gp.UnplacedFilters.ToList())
                        {
                            TryPlaceFilter(gp, f);
                        }
                    }
                }
            }

            // Finally optimise the Child Graph Patterns
            foreach (GraphPattern cgp in gp.ChildGraphPatterns)
            {
                // At each point the variables that have occurred are those in the Triple Patterns and
                // those in previous Graph Patterns
                cgp.Optimise(this, ourVariables);
                ourVariables.AddRange(cgp.Variables);
            }

            // Note: Any remaining Unplaced Filters/Assignments are OK since the ToAlgebra() method of a GraphPattern
            // will take care of placing these appropriately
        }
Ejemplo n.º 33
0
 /// <summary>
 /// Creates a new Having Clause
 /// </summary>
 /// <param name="pattern">Pattern</param>
 /// <param name="having">Having Clause</param>
 public Having(ISparqlAlgebra pattern, ISparqlFilter having)
 {
     this._pattern = pattern;
     this._having = having;
 }
Ejemplo n.º 34
0
 /// <summary>
 /// Creates a new LeftJoin where there is a Filter over the join
 /// </summary>
 /// <param name="lhs">LHS Pattern</param>
 /// <param name="rhs">RHS Pattern</param>
 /// <param name="filter">Filter to decide which RHS solutions are valid</param>
 public LeftJoin(ISparqlAlgebra lhs, ISparqlAlgebra rhs, ISparqlFilter filter)
     : this(lhs, rhs)
 {
     _filter = filter;
 }