Esempio n. 1
0
        private void TestSubstitution(SparqlQuery q, String findVar, INode replaceTerm, IEnumerable <String> expected, IEnumerable <String> notExpected)
        {
            Console.WriteLine("Input Query:");
            Console.WriteLine(this._formatter.Format(q));
            Console.WriteLine();

            ISparqlAlgebra algebra = q.ToAlgebra();
            VariableSubstitutionTransformer transformer = new VariableSubstitutionTransformer(findVar, replaceTerm);

            try
            {
                ISparqlAlgebra resAlgebra = transformer.Optimise(algebra);
                algebra = resAlgebra;
            }
            catch (Exception ex)
            {
                //Ignore errors
                Console.WriteLine("Error Transforming - " + ex.Message);
                Console.WriteLine(ex.StackTrace);
                Console.WriteLine();
            }

            SparqlQuery resQuery = algebra.ToQuery();
            String      resText  = this._formatter.Format(resQuery);

            Console.WriteLine("Resulting Query:");
            Console.WriteLine(resText);
            Console.WriteLine();

            foreach (String x in expected)
            {
                Assert.IsTrue(resText.Contains(x), "Expected Transformed Query to contain string '" + x + "'");
            }
            foreach (String x in notExpected)
            {
                Assert.IsFalse(resText.Contains(x), "Transformed Query contained string '" + x + "' which was not expected");
            }
        }
Esempio n. 2
0
        /// <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);
        }