Exemple #1
0
        /// <summary>
        /// Optimises BGPs in the Algebra to use Filter() and Extend() rather than the embedded FILTER and BIND
        /// </summary>
        /// <param name="algebra">Algebra to optimise</param>
        /// <returns></returns>
        public ISparqlAlgebra Optimise(ISparqlAlgebra algebra)
        {
            if (algebra is IAbstractJoin)
            {
                return(((IAbstractJoin)algebra).Transform(this));
            }
            else if (algebra is IUnaryOperator)
            {
                return(((IUnaryOperator)algebra).Transform(this));
            }
            else if (algebra is IBgp)
            {
                IBgp current = (IBgp)algebra;
                if (current.PatternCount == 0)
                {
                    return(current);
                }
                else
                {
                    ISparqlAlgebra        result   = new Bgp();
                    List <ITriplePattern> patterns = new List <ITriplePattern>();
                    List <ITriplePattern> ps       = new List <ITriplePattern>(current.TriplePatterns.ToList());
                    for (int i = 0; i < current.PatternCount; i++)
                    {
                        if (!(ps[i] is TriplePattern))
                        {
                            //First ensure that if we've found any other Triple Patterns up to this point
                            //we dump this into a BGP and join with the result so far
                            if (patterns.Count > 0)
                            {
                                result = Join.CreateJoin(result, new Bgp(patterns));
                                patterns.Clear();
                            }

                            //Then generate the appropriate strict algebra operator
                            if (ps[i] is FilterPattern)
                            {
                                result = new Filter(result, ((FilterPattern)ps[i]).Filter);
                            }
                            else if (ps[i] is BindPattern)
                            {
                                BindPattern bind = (BindPattern)ps[i];
                                result = new Extend(result, bind.AssignExpression, bind.VariableName);
                            }
                            else if (ps[i] is LetPattern)
                            {
                                LetPattern let = (LetPattern)ps[i];
                                result = new Extend(result, let.AssignExpression, let.VariableName);
                            }
                            else if (ps[i] is SubQueryPattern)
                            {
                                SubQueryPattern sq = (SubQueryPattern)ps[i];
                                result = Join.CreateJoin(result, new SubQuery(sq.SubQuery));
                            }
                            else if (ps[i] is PropertyPathPattern)
                            {
                                PropertyPathPattern pp = (PropertyPathPattern)ps[i];
                                result = Join.CreateJoin(result, new PropertyPath(pp.Subject, pp.Path, pp.Object));
                            }
                        }
                        else
                        {
                            patterns.Add(ps[i]);
                        }
                    }

                    if (patterns.Count == current.PatternCount)
                    {
                        //If count of remaining patterns same as original pattern count there was no optimisation
                        //to do so return as is
                        return(current);
                    }
                    else if (patterns.Count > 0)
                    {
                        //If any patterns left at end join as a BGP with result so far
                        result = Join.CreateJoin(result, new Bgp(patterns));
                        return(result);
                    }
                    else
                    {
                        return(result);
                    }
                }
            }
            else if (algebra is ITerminalOperator)
            {
                return(algebra);
            }
            else
            {
                return(algebra);
            }
        }
        private void TryParseLetAssignment(SparqlQueryParserContext context, GraphPattern p)
        {
            if (context.SyntaxMode == SparqlQuerySyntax.Sparql_1_0) throw new RdfParseException("LET assignment is not supported in SPARQL 1.0");
            if (context.SyntaxMode == SparqlQuerySyntax.Sparql_1_1) throw new RdfParseException("LET assignment is not supported in SPARQL 1.1 - use BIND assignment instead");

            IToken variable;
            ISparqlExpression expr;

            //Firstly we expect an opening bracket, a variable and then an assignment operator
            IToken next = context.Tokens.Dequeue();
            if (next.TokenType == Token.LEFTBRACKET)
            {
                next = context.Tokens.Dequeue();
                if (next.TokenType == Token.VARIABLE)
                {
                    variable = next;
                    context.Query.AddVariable(variable.Value, false);
                    next = context.Tokens.Dequeue();
                    if (next.TokenType == Token.ASSIGNMENT)
                    {
                        //See if there is a valid expression for the right hand side of the assignment
                        next = context.Tokens.Peek();
                        switch (next.TokenType)
                        {
                            case Token.ABS:
                            case Token.BNODE:
                            case Token.BOUND:
                            case Token.CEIL:
                            case Token.COALESCE:
                            case Token.CONCAT:
                            case Token.DATATYPEFUNC:
                            case Token.DAY:
                            case Token.ENCODEFORURI:
                            case Token.EXISTS:
                            case Token.FLOOR:
                            case Token.HOURS:
                            case Token.IF:
                            case Token.IRI:
                            case Token.ISBLANK:
                            case Token.ISIRI:
                            case Token.ISLITERAL:
                            case Token.ISNUMERIC:
                            case Token.ISURI:
                            case Token.LANG:
                            case Token.LANGMATCHES:
                            case Token.LCASE:
                            case Token.MINUTES:
                            case Token.MONTH:
                            case Token.NOTEXISTS:
                            case Token.NOW:
                            case Token.RAND:
                            case Token.REGEX:
                            case Token.ROUND:
                            case Token.SAMETERM:
                            case Token.SECONDS:
                            case Token.SHA1:
                            case Token.SHA224:
                            case Token.SHA256:
                            case Token.SHA384:
                            case Token.SHA512:
                            case Token.STR:
                            case Token.CONTAINS:
                            case Token.STRDT:
                            case Token.STRENDS:
                            case Token.STRLANG:
                            case Token.STRLEN:
                            case Token.STRSTARTS:
                            case Token.SUBSTR:
                            case Token.TIMEZONE:
                            case Token.TZ:
                            case Token.UCASE:
                            case Token.URIFUNC:
                            case Token.YEAR:
                            case Token.URI:
                            case Token.QNAME:
                                expr = this.TryParseFunctionExpression(context);
                                break;
                            case Token.LEFTBRACKET:
                                context.Tokens.Dequeue();
                                expr = this.TryParseExpression(context, false);
                                break;
                            case Token.VARIABLE:
                                context.Tokens.Dequeue();
                                expr = new VariableExpressionTerm(next.Value);
                                break;
                            default:
                                throw ParserHelper.Error("Unexpected Token '" + next.GetType().ToString() + "' encountered, expected a Token which was valid as the start of an expression for the right hand side of a LET assignment", next);
                        }

                        //Finally expect a Right Bracket to terminate the LET
                        next = context.Tokens.Dequeue();
                        if (next.TokenType != Token.RIGHTBRACKET)
                        {
                            throw ParserHelper.Error("Unexpected Token '" + next.GetType().ToString() + "' encountered, expected a Right Bracket to terminate the LET assignment", next);
                        }
                        
                        //Create a Let Pattern and add to the Query appropriately
                        LetPattern let = new LetPattern(variable.Value.Substring(1), expr);
                        if (Options.QueryOptimisation)
                        {
                            p.AddAssignment(let);
                        }
                        else
                        {
                            //When Optimisation is turned off we'll just stick the Let in the Triples Pattern where it occurs
                            //since we're not going to do any Triple Pattern ordering, Assignment or FILTER placement
                            p.AddTriplePattern(let);
                        }
                    }
                    else
                    {
                        throw ParserHelper.Error("Unexpected Token '" + next.GetType().ToString() + "' encountered, expected an Assignment operator as part of a LET assignment", next);
                    }
                }
                else
                {
                    throw ParserHelper.Error("Unexpected Token '" + next.GetType().ToString() + "' encountered, expected a Variable as the first item in a LET assignment", next);
                }
            }
            else
            {
                throw ParserHelper.Error("Unexpected Token '" + next.GetType().ToString() + "' encountered, expected a Left Bracket to start a LET assignment after a LET Keyword", next);
            }
        }
Exemple #3
0
        /// <summary>
        /// Formats a Triple Pattern in nicely formatted SPARQL syntax
        /// </summary>
        /// <param name="tp">Triple Pattern</param>
        /// <returns></returns>
        public virtual String Format(ITriplePattern tp)
        {
            StringBuilder output = new StringBuilder();

            if (tp is TriplePattern)
            {
                TriplePattern match = (TriplePattern)tp;
                output.Append(this.Format(match.Subject, TripleSegment.Subject));
                output.Append(' ');
                output.Append(this.Format(match.Predicate, TripleSegment.Predicate));
                output.Append(' ');
                output.Append(this.Format(match.Object, TripleSegment.Object));
                output.Append(" .");
            }
            else if (tp is FilterPattern)
            {
                FilterPattern filter = (FilterPattern)tp;
                output.Append("FILTER(");
                output.Append(this.FormatExpression(filter.Filter.Expression));
                output.Append(")");
            }
            else if (tp is SubQueryPattern)
            {
                SubQueryPattern subquery = (SubQueryPattern)tp;
                output.AppendLine("{");
                output.AppendLineIndented(this.Format(subquery.SubQuery), 2);
                output.AppendLine("}");
            }
            else if (tp is PropertyPathPattern)
            {
                PropertyPathPattern path = (PropertyPathPattern)tp;
                output.Append(this.Format(path.Subject, TripleSegment.Subject));
                output.Append(' ');
                output.Append(this.FormatPath(path.Path));
                output.Append(' ');
                output.Append(this.Format(path.Object, TripleSegment.Object));
                output.Append(" .");
            }
            else if (tp is LetPattern)
            {
                LetPattern let = (LetPattern)tp;
                output.Append("LET(?");
                output.Append(let.VariableName);
                output.Append(" := ");
                output.Append(this.FormatExpression(let.AssignExpression));
                output.Append(")");
            }
            else if (tp is BindPattern)
            {
                BindPattern bind = (BindPattern)tp;
                output.Append("BIND (");
                output.Append(this.FormatExpression(bind.AssignExpression));
                output.Append(" AS ?");
                output.Append(bind.VariableName);
                output.Append(")");
            }
            else
            {
                throw new RdfOutputException("Unable to Format an unknown ITriplePattern implementation as a String");
            }

            return(output.ToString());
        }
Exemple #4
0
        /// <summary>
        /// Attempts to do variable substitution within the given algebra
        /// </summary>
        /// <param name="algebra">Algebra</param>
        /// <returns></returns>
        public ISparqlAlgebra Optimise(ISparqlAlgebra algebra)
        {
            //By default we are only safe to replace objects in a scope if we are replacing with a constant
            //Note that if we also make a replace in a subject/predicate position for a variable replace then
            //that makes object replacement safe for that scope only
            bool canReplaceObjects = (this._canReplaceCustom ? this._canReplaceObjects : this._replaceItem is NodeMatchPattern);

            if (algebra is IBgp)
            {
                IBgp bgp = (IBgp)algebra;
                if (bgp.PatternCount == 0)
                {
                    return(bgp);
                }

                //Do variable substitution on the patterns
                List <ITriplePattern> ps = new List <ITriplePattern>();
                foreach (ITriplePattern p in bgp.TriplePatterns)
                {
                    if (p is TriplePattern)
                    {
                        TriplePattern tp   = (TriplePattern)p;
                        PatternItem   subj = tp.Subject.VariableName != null && tp.Subject.VariableName.Equals(this._findVar) ? this._replaceItem : tp.Subject;
                        if (ReferenceEquals(subj, this._replaceItem))
                        {
                            canReplaceObjects = (this._canReplaceCustom ? this._canReplaceObjects : true);
                        }
                        PatternItem pred = tp.Predicate.VariableName != null && tp.Predicate.VariableName.Equals(this._findVar) ? this._replaceItem : tp.Predicate;
                        if (ReferenceEquals(pred, this._replaceItem))
                        {
                            canReplaceObjects = (this._canReplaceCustom ? this._canReplaceObjects : true);
                        }
                        PatternItem obj = tp.Object.VariableName != null && tp.Object.VariableName.Equals(this._findVar) ? this._replaceItem : tp.Object;
                        if (ReferenceEquals(obj, this._replaceItem) && !canReplaceObjects)
                        {
                            throw new Exception("Unable to substitute a variable into the object position in this scope");
                        }
                        ps.Add(new TriplePattern(subj, pred, obj));
                    }
                    else if (p is FilterPattern)
                    {
                        FilterPattern fp = (FilterPattern)p;
                        ps.Add(new FilterPattern(new UnaryExpressionFilter(this.Transform(fp.Filter.Expression))));
                    }
                    else if (p is BindPattern)
                    {
                        BindPattern bp = (BindPattern)p;
                        ps.Add(new BindPattern(bp.VariableName, this.Transform(bp.AssignExpression)));
                    }
                    else if (p is LetPattern)
                    {
                        LetPattern lp = (LetPattern)p;
                        ps.Add(new LetPattern(lp.VariableName, this.Transform(lp.AssignExpression)));
                    }
                    else if (p is SubQueryPattern)
                    {
                        throw new RdfQueryException("Cannot do variable substitution when a sub-query is present");
                    }
                    else if (p is PropertyPathPattern)
                    {
                        throw new RdfQueryException("Cannot do variable substitution when a property path is present");
                    }
                    else
                    {
                        throw new RdfQueryException("Cannot do variable substitution on unknown triple patterns");
                    }
                }
                return(new Bgp(ps));
            }
            else if (algebra is Service)
            {
                throw new RdfQueryException("Cannot do variable substitution when a SERVICE clause is present");
            }
            else if (algebra is SubQuery)
            {
                throw new RdfQueryException("Cannot do variable substitution when a sub-query is present");
            }
            else if (algebra is IPathOperator)
            {
                throw new RdfQueryException("Cannot do variable substitution when a property path is present");
            }
            else if (algebra is Algebra.Graph)
            {
                Algebra.Graph g = (Algebra.Graph)((IUnaryOperator)algebra).Transform(this);
                if (g.GraphSpecifier is VariableToken && g.GraphSpecifier.Value.Equals("?" + this._findVar))
                {
                    if (this._replaceToken != null)
                    {
                        return(new Algebra.Graph(g.InnerAlgebra, this._replaceToken));
                    }
                    else
                    {
                        throw new RdfQueryException("Cannot do a variable substitution when the variable is used for a GRAPH specifier and the replacement term is not a URI");
                    }
                }
                else
                {
                    return(g);
                }
            }
            else if (algebra is IUnaryOperator)
            {
                return(((IUnaryOperator)algebra).Transform(this));
            }
            else if (algebra is IAbstractJoin)
            {
                return(((IAbstractJoin)algebra).Transform(this));
            }
            else if (algebra is ITerminalOperator)
            {
                return(algebra);
            }
            else
            {
                throw new RdfQueryException("Cannot do variable substitution on unknown algebra");
            }
        }