예제 #1
0
 /// <summary>
 /// Optimises the Algebra to use Identity Filters where applicable
 /// </summary>
 /// <param name="algebra">Algebra</param>
 /// <returns></returns>
 public ISparqlAlgebra Optimise(ISparqlAlgebra algebra)
 {
     try
     {
         if (algebra is Filter)
         {
             Filter f = (Filter)algebra;
             String var;
             INode  term;
             bool   equals = false;
             if (IsIdentityExpression(f.SparqlFilter.Expression, out var, out term, out equals))
             {
                 try
                 {
                     // Try to use the extend style optimization
                     VariableSubstitutionTransformer transformer = new VariableSubstitutionTransformer(var, term);
                     ISparqlAlgebra extAlgebra = transformer.Optimise(f.InnerAlgebra);
                     return(new Extend(extAlgebra, new ConstantTerm(term), var));
                 }
                 catch
                 {
                     // Fall back to simpler Identity Filter
                     if (equals)
                     {
                         return(new IdentityFilter(Optimise(f.InnerAlgebra), var, new ConstantTerm(term)));
                     }
                     else
                     {
                         return(new SameTermFilter(Optimise(f.InnerAlgebra), var, new ConstantTerm(term)));
                     }
                 }
             }
             else
             {
                 return(f.Transform(this));
             }
         }
         else if (algebra is IAbstractJoin)
         {
             return(((IAbstractJoin)algebra).Transform(this));
         }
         else if (algebra is IUnaryOperator)
         {
             return(((IUnaryOperator)algebra).Transform(this));
         }
         else
         {
             return(algebra);
         }
     }
     catch
     {
         return(algebra);
     }
 }
예제 #2
0
 /// <summary>
 /// Optimises the Algebra to use implict joins where applicable
 /// </summary>
 /// <param name="algebra">Algebra</param>
 /// <returns></returns>
 public ISparqlAlgebra Optimise(ISparqlAlgebra algebra)
 {
     try
     {
         if (algebra is Filter)
         {
             Filter f = (Filter)algebra;
             String lhsVar, rhsVar;
             bool   equals;
             if (this.IsImplicitJoinExpression(f.SparqlFilter.Expression, out lhsVar, out rhsVar, out equals))
             {
                 //We must ensure that both variables are in scope
                 List <String> vars = f.InnerAlgebra.Variables.ToList();
                 if (vars.Contains(lhsVar) && vars.Contains(rhsVar))
                 {
                     //Try to use the extend style optimization
                     VariableSubstitutionTransformer transformer = new VariableSubstitutionTransformer(rhsVar, lhsVar);
                     if (!equals)
                     {
                         transformer.CanReplaceObjects = true;
                     }
                     ISparqlAlgebra extAlgebra = transformer.Optimise(f.InnerAlgebra);
                     return(new Extend(extAlgebra, new VariableTerm(lhsVar), rhsVar));
                 }
                 else
                 {
                     return(f.Transform(this));
                 }
             }
             else
             {
                 return(f.Transform(this));
             }
         }
         else if (algebra is IAbstractJoin)
         {
             return(((IAbstractJoin)algebra).Transform(this));
         }
         else if (algebra is IUnaryOperator)
         {
             return(((IUnaryOperator)algebra).Transform(this));
         }
         else
         {
             return(algebra);
         }
     }
     catch
     {
         return(algebra);
     }
 }
예제 #3
0
 /// <summary>
 /// Optimises the Algebra to use implict joins where applicable
 /// </summary>
 /// <param name="algebra">Algebra</param>
 /// <returns></returns>
 public ISparqlAlgebra Optimise(ISparqlAlgebra algebra)
 {
     try
     {
         if (algebra is Filter)
         {
             Filter f = (Filter)algebra;
             String lhsVar, rhsVar;
             bool   equals;
             if (IsImplicitJoinExpression(f.SparqlFilter.Expression, out lhsVar, out rhsVar, out equals))
             {
                 // We must ensure that both variables are in scope
                 List <String> vars = f.InnerAlgebra.Variables.ToList();
                 if (vars.Contains(lhsVar) && vars.Contains(rhsVar))
                 {
                     try
                     {
                         // Try to use the extend style optimization
                         VariableSubstitutionTransformer transformer = new VariableSubstitutionTransformer(rhsVar, lhsVar);
                         if (!equals || Options.UnsafeOptimisation)
                         {
                             transformer.CanReplaceObjects = true;
                         }
                         ISparqlAlgebra extAlgebra = transformer.Optimise(f.InnerAlgebra);
                         return(new Extend(extAlgebra, new VariableTerm(lhsVar), rhsVar));
                     }
                     catch
                     {
                         // See if the Filtered Product style optimization applies instead
                         int splitPoint = -1;
                         if (IsDisjointOperation(f.InnerAlgebra, lhsVar, rhsVar, out splitPoint))
                         {
                             if (splitPoint > -1)
                             {
                                 // Means the inner algebra is a BGP we can split into two parts
                                 IBgp bgp = (IBgp)f.InnerAlgebra;
                                 return(new FilteredProduct(new Bgp(bgp.TriplePatterns.Take(splitPoint)), new Bgp(bgp.TriplePatterns.Skip(splitPoint)), f.SparqlFilter.Expression));
                             }
                             else
                             {
                                 // Means that the inner algebra is a Join where the sides are disjoint
                                 IJoin join = (IJoin)f.InnerAlgebra;
                                 return(new FilteredProduct(join.Lhs, join.Rhs, f.SparqlFilter.Expression));
                             }
                         }
                         else
                         {
                             return(f.Transform(this));
                         }
                     }
                 }
                 else
                 {
                     return(f.Transform(this));
                 }
             }
             else
             {
                 return(f.Transform(this));
             }
         }
         else if (algebra is IAbstractJoin)
         {
             return(((IAbstractJoin)algebra).Transform(this));
         }
         else if (algebra is IUnaryOperator)
         {
             return(((IUnaryOperator)algebra).Transform(this));
         }
         else
         {
             return(algebra);
         }
     }
     catch
     {
         return(algebra);
     }
 }
예제 #4
0
 /// <summary>
 /// Optimises the Algebra to use Identity Filters where applicable
 /// </summary>
 /// <param name="algebra">Algebra</param>
 /// <returns></returns>
 public ISparqlAlgebra Optimise(ISparqlAlgebra algebra)
 {
     try
     {
         if (algebra is Filter)
         {
             Filter f = (Filter)algebra;
             String var;
             INode term;
             bool equals = false;
             if (this.IsIdentityExpression(f.SparqlFilter.Expression, out var, out term, out equals))
             {
                 try
                 {
                     //Try to use the extend style optimization
                     VariableSubstitutionTransformer transformer = new VariableSubstitutionTransformer(var, term);
                     ISparqlAlgebra extAlgebra = transformer.Optimise(f.InnerAlgebra);
                     return new Extend(extAlgebra, new ConstantTerm(term), var);
                 }
                 catch
                 {
                     //Fall back to simpler Identity Filter
                     if (equals)
                     {
                         return new IdentityFilter(this.Optimise(f.InnerAlgebra), var, new ConstantTerm(term));
                     }
                     else
                     {
                         return new SameTermFilter(this.Optimise(f.InnerAlgebra), var, new ConstantTerm(term));
                     }
                 }
             }
             else
             {
                 return f.Transform(this);
             }
         }
         else if (algebra is IAbstractJoin)
         {
             return ((IAbstractJoin)algebra).Transform(this);
         }
         else if (algebra is IUnaryOperator)
         {
             return ((IUnaryOperator)algebra).Transform(this);
         }
         else
         {
             return algebra;
         }
     }
     catch
     {
         return algebra;
     }
 }
        /// <summary>
        /// Runs the optimisation against a Filter algebra
        /// </summary>
        /// <param name="filter">The Filter algebra to optimise</param>
        /// <param name="optimisedAlgebra">Receives the optimised algebra if optimisation was performed or the input algebra otherwise</param>
        /// <returns>True if an optimisation was performed, false otherwise</returns>
        /// <remarks>
        /// <para>This implementation currently handles the simple case of a Filter applied to a BGP where the filter
        /// expression is either a single EqualsExpression or SameTermExpression or an AndExpression containing one or more
        /// EqualsExpression or SameTermExpression arguments. The implementation ensures that the replaced variable is still
        /// available to the outer algebra by inserting a BindPattern into the BGP. If the filter expression is a single 
        /// EqualsExpression or SameTermExpression, the optimiser will also strip this out of the algebra, but with an
        /// AndExpression it will leave the full filter expression untouched.</para>
        /// <para>The implementation will replace only URI and PlainLiteral types</para>
        /// TODO: It should be possible to remove EqualsExpression and SameTermExpression instances from the AndExpression arguments and then either strip it out (if it has no remaining arguments), or optimise it to a single expression (if it has one remaining argument)
        /// </remarks>
        private bool OptimiseFilter(IFilter filter, out ISparqlAlgebra optimisedAlgebra)
        {
            if (!(filter.InnerAlgebra is Bgp))
            {
                // Need a BGP to be able to insert BindPatterns for replaced variables
                optimisedAlgebra = filter;
                return false;
            }

            var filterExpression = filter.SparqlFilter.Expression;
            var replacementTerms = new Dictionary<string, INode>();
            string var;
            INode term;
            bool equals;
            
            // Currently only handle the simple filter cases of a single identity expression
            // or an AND of expressions
            if (IsIdentityExpression(filterExpression, out var, out term, out equals))
            {
                if (CanOptimize(term))
                {
                    replacementTerms.Add(var, term);
                }
            }
            else if (filterExpression is AndExpression)
            {
                foreach (var arg in filterExpression.Arguments)
                {
                    if (IsIdentityExpression(arg, out var, out term, out equals) && CanOptimize(term))
                    {
                            replacementTerms.Add(var, term);
                    }
                    else
                    {
                        foreach (var variable in arg.Variables) {
                            // Cannot guarantee that the argument doesn't imply some other possible binding for the variables
                            replacementTerms.Remove(variable);
                        }
                    }
                }
            }

            if (replacementTerms.Any())
            {
                var optimisedInner = filter.InnerAlgebra as Bgp;
                foreach (var replacementEntry in replacementTerms)
                {
                    try
                    {
                        // Replace the variable with a constant term wherever it appears and then add a Bind pattern
                        // to ensure that the variable is bound for use in the outer algebra
                        var t = new VariableSubstitutionTransformer(replacementEntry.Key, replacementEntry.Value);
                        optimisedInner = t.Optimise(optimisedInner) as Bgp;
                        optimisedInner =
                            new Bgp(
                                optimisedInner.TriplePatterns.Concat(new[]
                                {new BindPattern(replacementEntry.Key, new ConstantTerm(replacementEntry.Value))}));
                    }
                    catch (RdfQueryException)
                    {
                        // Could not perform this replacement.
                    }
                }
                if (filterExpression is AndExpression)
                {
                    // Keep the filter as it may contain other necessary expressions
                    // TODO: Could try to remove the identity expressions here ?
                    optimisedAlgebra = new Filter(optimisedInner, filter.SparqlFilter);
                }
                else
                {
                    // Can optimise away the filter entirely
                    optimisedAlgebra = optimisedInner;
                }
                return true;
            }
            optimisedAlgebra = filter;
            return false;
        }
예제 #6
0
 /// <summary>
 /// Optimises the Algebra to use implict joins where applicable
 /// </summary>
 /// <param name="algebra">Algebra</param>
 /// <returns></returns>
 public ISparqlAlgebra Optimise(ISparqlAlgebra algebra)
 {
     try
     {
         if (algebra is Filter)
         {
             Filter f = (Filter)algebra;
             String lhsVar, rhsVar;
             bool equals;
             if (this.IsImplicitJoinExpression(f.SparqlFilter.Expression, out lhsVar, out rhsVar, out equals))
             {
                 //We must ensure that both variables are in scope
                 List<String> vars = f.InnerAlgebra.Variables.ToList();
                 if (vars.Contains(lhsVar) && vars.Contains(rhsVar))
                 {
                     //Try to use the extend style optimization
                     VariableSubstitutionTransformer transformer = new VariableSubstitutionTransformer(rhsVar, lhsVar);
                     if (!equals) transformer.CanReplaceObjects = true;
                     ISparqlAlgebra extAlgebra = transformer.Optimise(f.InnerAlgebra);
                     return new Extend(extAlgebra, new VariableTerm(lhsVar), rhsVar);
                 }
                 else
                 {
                     return f.Transform(this);
                 }
             }
             else
             {
                 return f.Transform(this);
             }
         }
         else if (algebra is IAbstractJoin)
         {
             return ((IAbstractJoin)algebra).Transform(this);
         }
         else if (algebra is IUnaryOperator)
         {
             return ((IUnaryOperator)algebra).Transform(this);
         }
         else
         {
             return algebra;
         }
     }
     catch
     {
         return algebra;
     }
 }