Example #1
0
        /// <summary>
        /// Optimises the algebra so that all Node terms are virtualised
        /// </summary>
        /// <param name="algebra">Algebra</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());
                    TNodeID nullID = this._provider.NullID;

                    for (int i = 0; i < current.PatternCount; i++)
                    {
                        if (ps[i] is FilterPattern || ps[i] is BindPattern)
                        {
                            //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();
                            }
                            if (ps[i] is FilterPattern)
                            {
                                result = new Filter(result, ((FilterPattern)ps[i]).Filter);
                            }
                            else
                            {
                                BindPattern bind = (BindPattern)ps[i];
                                result = new Extend(result, bind.AssignExpression, bind.VariableName);
                            }
                        }
                        else
                        {
                            //Convert Terms in the Pattern into Virtual Nodes
                            TriplePattern tp = (TriplePattern)ps[i];
                            PatternItem   subj, pred, obj;
                            if (tp.Subject is NodeMatchPattern)
                            {
                                TNodeID id = this._provider.GetID(((NodeMatchPattern)tp.Subject).Node);
                                if (id == null || id.Equals(nullID))
                                {
                                    result = new NullOperator(current.Variables);
                                    break;
                                }
                                else
                                {
                                    subj = new NodeMatchPattern(this.CreateVirtualNode(id, ((NodeMatchPattern)tp.Subject).Node));
                                }
                            }
                            else
                            {
                                subj = tp.Subject;
                            }
                            if (tp.Predicate is NodeMatchPattern)
                            {
                                TNodeID id = this._provider.GetID(((NodeMatchPattern)tp.Predicate).Node);
                                if (id == null || id.Equals(nullID))
                                {
                                    result = new NullOperator(current.Variables);
                                    break;
                                }
                                else
                                {
                                    pred = new NodeMatchPattern(this.CreateVirtualNode(id, ((NodeMatchPattern)tp.Predicate).Node));
                                }
                            }
                            else
                            {
                                pred = tp.Predicate;
                            }
                            if (tp.Object is NodeMatchPattern)
                            {
                                TNodeID id = this._provider.GetID(((NodeMatchPattern)tp.Object).Node);
                                if (id == null || id.Equals(nullID))
                                {
                                    result = new NullOperator(current.Variables);
                                    break;
                                }
                                else
                                {
                                    obj = new NodeMatchPattern(this.CreateVirtualNode(id, ((NodeMatchPattern)tp.Object).Node));
                                }
                            }
                            else
                            {
                                obj = tp.Object;
                            }
                            patterns.Add(new TriplePattern(subj, pred, obj));
                        }
                    }

                    if (result is NullOperator)
                    {
                        return(result);
                    }
                    else 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);
            }
        }
Example #2
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);
            }
        }
Example #3
0
        /// <summary>
        /// Gets the Algebra representation of the Graph Pattern
        /// </summary>
        /// <returns></returns>
        public ISparqlAlgebra ToAlgebra()
        {
            if (_isUnion)
            {
                // If this Graph Pattern represents a UNION of Graph Patterns turn into a series of UNIONs
                ISparqlAlgebra union = new Union(_graphPatterns[0].ToAlgebra(), _graphPatterns[1].ToAlgebra());
                if (_graphPatterns.Count > 2)
                {
                    for (int i = 2; i < _graphPatterns.Count; i++)
                    {
                        union = new Union(union, _graphPatterns[i].ToAlgebra());
                    }
                }
                // Apply Inline Data
                if (HasInlineData)
                {
                    union = Join.CreateJoin(union, new Bindings(_data));
                }
                // If there's a FILTER apply it over the Union
                if (_isFiltered && (_filter != null || _unplacedFilters.Count > 0))
                {
                    return(new Filter(union, Filter));
                }
                return(union);
            }

            // Terminal graph pattern
            if (_graphPatterns.Count == 0)
            {
                // If there are no Child Graph Patterns then this is a BGP
                ISparqlAlgebra bgp = new Bgp(_triplePatterns);
                if (_unplacedAssignments.Count > 0)
                {
                    // If we have any unplaced LETs these get Extended onto the BGP
                    foreach (IAssignmentPattern p in _unplacedAssignments)
                    {
                        bgp = new Extend(bgp, p.AssignExpression, p.VariableName);
                    }
                }
                if (IsGraph)
                {
                    bgp = Algebra.Graph.ApplyGraph(bgp, GraphSpecifier);
                }
                else if (IsService)
                {
                    bgp = new Service(GraphSpecifier, this, IsSilent);
                }

                // Apply Inline Data
                if (HasInlineData)
                {
                    bgp = Join.CreateJoin(bgp, new Bindings(_data));
                }
                if (_isFiltered && (_filter != null || _unplacedFilters.Count > 0))
                {
                    if (_isOptional && !(_isExists || _isNotExists))
                    {
                        // If we contain an unplaced FILTER and we're an OPTIONAL then the FILTER
                        // applies over the LEFT JOIN and will have been added elsewhere in the Algebra transform
                        return(bgp);
                    }

                    // If we contain an unplaced FILTER and we're not an OPTIONAL the FILTER
                    // applies here
                    return(new Filter(bgp, Filter));
                }
                // We're not filtered (or all FILTERs were placed in the BGP) so we're just a BGP
                return(bgp);
            }

            // Create a basic BGP to start with
            ISparqlAlgebra complex = new Bgp();

            if (_triplePatterns.Count > 0)
            {
                complex = new Bgp(_triplePatterns);
            }

            // Apply Inline Data
            // If this Graph Pattern had child patterns before this Graph Pattern then we would
            // have broken the BGP and not added the Inline Data here so it's always safe to apply this here
            if (HasInlineData)
            {
                complex = Join.CreateJoin(complex, new Bindings(_data));
            }

            // Then Join each of the Graph Patterns as appropriate
            foreach (GraphPattern gp in _graphPatterns)
            {
                if (gp.IsGraph)
                {
                    // A GRAPH clause means a Join of the current pattern to a Graph clause
                    ISparqlAlgebra gpAlgebra = gp.ToAlgebra();
                    complex = Join.CreateJoin(complex, Algebra.Graph.ApplyGraph(gpAlgebra, gp.GraphSpecifier));
                }
                else if (gp.IsOptional)
                {
                    if (gp.IsExists || gp.IsNotExists)
                    {
                        // An EXISTS/NOT EXISTS means an Exists Join of the current pattern to the EXISTS/NOT EXISTS clause
                        complex = new ExistsJoin(complex, gp.ToAlgebra(), gp.IsExists);
                    }
                    else
                    {
                        // An OPTIONAL means a Left Join of the current pattern to the OPTIONAL clause
                        // with a possible FILTER applied over the LeftJoin
                        if (gp.IsFiltered && gp.Filter != null)
                        {
                            // If the OPTIONAL clause has an unplaced FILTER it applies over the Left Join
                            complex = new LeftJoin(complex, gp.ToAlgebra(), gp.Filter);
                        }
                        else
                        {
                            complex = new LeftJoin(complex, gp.ToAlgebra());
                        }
                    }
                }
                else if (gp.IsMinus)
                {
                    // Always introduce a Minus here even if the Minus is disjoint since during evaluation we'll choose
                    // not to execute it if it's disjoint
                    complex = new Minus(complex, gp.ToAlgebra());
                }
                else if (gp.IsService)
                {
                    complex = Join.CreateJoin(complex, new Service(gp.GraphSpecifier, gp, gp.IsSilent));
                }
                else
                {
                    // Otherwise we just join the pattern to the existing pattern
                    complex = Join.CreateJoin(complex, gp.ToAlgebra());
                }
            }
            if (_unplacedAssignments.Count > 0)
            {
                // Unplaced assignments get Extended over the algebra so far here
                // complex = Join.CreateJoin(complex, new Bgp(this._unplacedAssignments.OfType<ITriplePattern>()));
                foreach (IAssignmentPattern p in _unplacedAssignments)
                {
                    complex = new Extend(complex, p.AssignExpression, p.VariableName);
                }
            }
            if (IsGraph)
            {
                complex = Algebra.Graph.ApplyGraph(complex, GraphSpecifier);
            }
            if (_isFiltered && (_filter != null || _unplacedFilters.Count > 0))
            {
                if (_isOptional && !(_isExists || _isNotExists))
                {
                    // If there's an unplaced FILTER and we're an OPTIONAL then the FILTER will
                    // apply over the LeftJoin and is applied elsewhere in the Algebra transform
                    return(complex);
                }
                else
                {
                    if (_filter != null || _unplacedFilters.Count > 0)
                    {
                        // If there's an unplaced FILTER and we're not an OPTIONAL pattern we apply
                        // the FILTER here
                        return(new Filter(complex, Filter));
                    }
                    else
                    {
                        return(complex);
                    }
                }
            }
            else
            {
                // If no FILTER just return the transform
                return(complex);
            }
        }
        /// <summary>
        /// Optimises the algebra so that all Node terms are virtualised.
        /// </summary>
        /// <param name="algebra">Algebra.</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());
                    TNodeID nullID = _provider.NullID;

                    for (int i = 0; i < current.PatternCount; i++)
                    {
                        if (ps[i].PatternType == TriplePatternType.Filter || ps[i].PatternType == TriplePatternType.BindAssignment || ps[i].PatternType == TriplePatternType.LetAssignment)
                        {
                            // 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();
                            }
                            if (ps[i].PatternType == TriplePatternType.Filter)
                            {
                                result = new Filter(result, new UnaryExpressionFilter(Transform(((IFilterPattern)ps[i]).Filter.Expression)));
                            }
                            else
                            {
                                IAssignmentPattern bind = (IAssignmentPattern)ps[i];
                                result = new Extend(result, Transform(bind.AssignExpression), bind.VariableName);
                            }
                        }
                        else if (ps[i].PatternType == TriplePatternType.Match)
                        {
                            // Convert Terms in the Pattern into Virtual Nodes
                            IMatchTriplePattern tp = (IMatchTriplePattern)ps[i];
                            PatternItem         subj, pred, obj;
                            if (tp.Subject is NodeMatchPattern)
                            {
                                TNodeID id = _provider.GetID(((NodeMatchPattern)tp.Subject).Node);
                                if (id == null || id.Equals(nullID))
                                {
                                    result = new NullOperator(current.Variables);
                                    break;
                                }
                                else
                                {
                                    subj = new NodeMatchPattern(CreateVirtualNode(id, ((NodeMatchPattern)tp.Subject).Node));
                                }
                            }
                            else
                            {
                                subj = tp.Subject;
                            }
                            if (tp.Predicate is NodeMatchPattern)
                            {
                                TNodeID id = _provider.GetID(((NodeMatchPattern)tp.Predicate).Node);
                                if (id == null || id.Equals(nullID))
                                {
                                    result = new NullOperator(current.Variables);
                                    break;
                                }
                                else
                                {
                                    pred = new NodeMatchPattern(CreateVirtualNode(id, ((NodeMatchPattern)tp.Predicate).Node));
                                }
                            }
                            else
                            {
                                pred = tp.Predicate;
                            }
                            if (tp.Object is NodeMatchPattern)
                            {
                                TNodeID id = _provider.GetID(((NodeMatchPattern)tp.Object).Node);
                                if (id == null || id.Equals(nullID))
                                {
                                    result = new NullOperator(current.Variables);
                                    break;
                                }
                                else
                                {
                                    obj = new NodeMatchPattern(CreateVirtualNode(id, ((NodeMatchPattern)tp.Object).Node));
                                }
                            }
                            else
                            {
                                obj = tp.Object;
                            }
                            patterns.Add(new TriplePattern(subj, pred, obj));
                        }
                        else
                        {
                            // Can't optimize if other pattern types involved
                            return(current);
                        }
                    }

                    if (result is NullOperator)
                    {
                        return(result);
                    }
                    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);
            }
        }
        /// <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)
            {
                // Don't integerfer with other optimisers which have added custom BGP implementations
                if (!(algebra is Bgp))
                {
                    return(algebra);
                }

                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++)
                    {
                        // Can't split the BGP if there are Blank Nodes present
                        if (!ps[i].HasNoBlankVariables)
                        {
                            return(current);
                        }

                        if (ps[i].PatternType != TriplePatternType.Match)
                        {
                            // 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
                            switch (ps[i].PatternType)
                            {
                            case TriplePatternType.Filter:
                                result = new Filter(result, ((IFilterPattern)ps[i]).Filter);
                                break;

                            case TriplePatternType.BindAssignment:
                            case TriplePatternType.LetAssignment:
                                IAssignmentPattern assignment = (IAssignmentPattern)ps[i];
                                result = new Extend(result, assignment.AssignExpression, assignment.VariableName);
                                break;

                            case TriplePatternType.SubQuery:
                                ISubQueryPattern sq = (ISubQueryPattern)ps[i];
                                result = Join.CreateJoin(result, new SubQuery(sq.SubQuery));
                                break;

                            case TriplePatternType.Path:
                                IPropertyPathPattern pp = (IPropertyPathPattern)ps[i];
                                result = Join.CreateJoin(result, new PropertyPath(pp.Subject, pp.Path, pp.Object));
                                break;

                            case TriplePatternType.PropertyFunction:
                                IPropertyFunctionPattern pf = (IPropertyFunctionPattern)ps[i];
                                result = new PropertyFunction(result, pf.PropertyFunction);
                                break;

                            default:
                                throw new RdfQueryException("Cannot apply strict algebra form to a BGP containing a unknown triple pattern type");
                            }
                        }
                        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);
            }
        }
Example #6
0
        /// <summary>
        /// Converts the Query into it's SPARQL Algebra representation (as represented in the Leviathan API)
        /// </summary>
        /// <returns></returns>
        public ISparqlAlgebra ToAlgebra()
        {
            //Depending on how the query gets built we may not have had graph pattern optimization applied
            //which we should do here if query optimization is enabled
            if (!this.IsOptimised && Options.QueryOptimisation)
            {
                this.Optimise();
            }

            //Firstly Transform the Root Graph Pattern to SPARQL Algebra
            ISparqlAlgebra algebra;

            if (this._rootGraphPattern != null)
            {
                if (Options.AlgebraOptimisation)
                {
                    //If using Algebra Optimisation may use a special algebra in some cases
                    switch (this.SpecialType)
                    {
                    case SparqlSpecialQueryType.DistinctGraphs:
                        algebra = new SelectDistinctGraphs(this.Variables.First(v => v.IsResultVariable).Name);
                        break;

                    case SparqlSpecialQueryType.AskAnyTriples:
                        algebra = new AskAnyTriples();
                        break;

                    case SparqlSpecialQueryType.NotApplicable:
                    default:
                        //If not just use the standard transform
                        algebra = this._rootGraphPattern.ToAlgebra();
                        break;
                    }
                }
                else
                {
                    //If not using Algebra Optimisation just use the standard transform
                    algebra = this._rootGraphPattern.ToAlgebra();
                }
            }
            else
            {
                //No root graph pattern means empty BGP
                algebra = new Bgp();
            }

            //If we have a top level VALUES clause then we'll add it into the algebra here
            if (this._bindings != null)
            {
                algebra = Join.CreateJoin(algebra, new Bindings(this._bindings));
            }

            //Then we apply any optimisers followed by relevant solution modifiers
            switch (this._type)
            {
            case SparqlQueryType.Ask:
                //Apply Algebra Optimisation is enabled
                if (Options.AlgebraOptimisation)
                {
                    algebra = this.ApplyAlgebraOptimisations(algebra);
                }
                return(new Ask(algebra));

            case SparqlQueryType.Construct:
            case SparqlQueryType.Describe:
            case SparqlQueryType.DescribeAll:
            case SparqlQueryType.Select:
            case SparqlQueryType.SelectAll:
            case SparqlQueryType.SelectAllDistinct:
            case SparqlQueryType.SelectAllReduced:
            case SparqlQueryType.SelectDistinct:
            case SparqlQueryType.SelectReduced:
                //Apply Algebra Optimisation if enabled
                if (Options.AlgebraOptimisation)
                {
                    algebra = this.ApplyAlgebraOptimisations(algebra);
                }

                //GROUP BY is the first thing applied
                //This applies if there is a GROUP BY or if there are aggregates
                //With no GROUP BY it produces a single group of all results
                if (this._groupBy != null || this._vars.Any(v => v.IsAggregate))
                {
                    algebra = new GroupBy(algebra, this._groupBy, this._vars.Where(v => v.IsAggregate));
                }

                //After grouping we do projection
                //We introduce an Extend for each Project Expression
                foreach (SparqlVariable var in this._vars)
                {
                    if (var.IsProjection)
                    {
                        algebra = new Extend(algebra, var.Projection, var.Name);
                    }
                }

                //Add HAVING clause after the projection
                if (this._having != null)
                {
                    algebra = new Having(algebra, this._having);
                }

                //We can then Order our results
                //We do ordering before we do Select but after Project so we can order by any of
                //the project expressions/aggregates and any variable in the results even if
                //it won't be output as a result variable
                if (this._orderBy != null)
                {
                    algebra = new OrderBy(algebra, this._orderBy);
                }

                //After Ordering we apply Select
                //Select effectively trims the results so only result variables are left
                //This doesn't apply to CONSTRUCT since any variable may be used in the Construct Template
                //so we don't want to eliminate anything
                if (this._type != SparqlQueryType.Construct)
                {
                    algebra = new Select(algebra, this.Variables);
                }

                //If we have a Distinct/Reduced then we'll apply those after Selection
                if (this._type == SparqlQueryType.SelectAllDistinct || this._type == SparqlQueryType.SelectDistinct)
                {
                    algebra = new Distinct(algebra);
                }
                else if (this._type == SparqlQueryType.SelectAllReduced || this._type == SparqlQueryType.SelectReduced)
                {
                    algebra = new Reduced(algebra);
                }

                //Finally we can apply any limit and/or offset
                if (this._limit >= 0 || this._offset > 0)
                {
                    algebra = new Slice(algebra, this._limit, this._offset);
                }

                return(algebra);

            default:
                throw new RdfQueryException("Unable to convert unknown Query Types to SPARQL Algebra");
            }
        }
Example #7
0
        /// <summary>
        /// Gets the Algebra representation of the Graph Pattern
        /// </summary>
        /// <returns></returns>
        public ISparqlAlgebra ToAlgebra()
        {
            if (this._isUnion)
            {
                //If this Graph Pattern represents a UNION of Graph Patterns turn into a series of UNIONs
                ISparqlAlgebra union = new Union(this._graphPatterns[0].ToAlgebra(), this._graphPatterns[1].ToAlgebra());
                if (this._graphPatterns.Count > 2)
                {
                    for (int i = 2; i < this._graphPatterns.Count; i++)
                    {
                        union = new Union(union, this._graphPatterns[i].ToAlgebra());
                    }
                }
                //If there's a FILTER apply it over the Union
                if (this._isFiltered && (this._filter != null || this._unplacedFilters.Count > 0))
                {
                    return(new Filter(union, this.Filter));
                }
                else
                {
                    return(union);
                }
            }
            else if (this._graphPatterns.Count == 0)
            {
                //If there are no Child Graph Patterns then this is a BGP
                ISparqlAlgebra bgp = new Bgp(this._triplePatterns);
                if (this._unplacedAssignments.Count > 0)
                {
                    //If we have any unplaced LETs these get Joined onto the BGP
                    bgp = Join.CreateJoin(bgp, new Bgp(this._unplacedAssignments));
                }
                if (this._isFiltered && (this._filter != null || this._unplacedFilters.Count > 0))
                {
                    if (this._isOptional && !(this._isExists || this._isNotExists))
                    {
                        //If we contain an unplaced FILTER and we're an OPTIONAL then the FILTER
                        //applies over the LEFT JOIN and will have been added elsewhere in the Algebra transform
                        return(bgp);
                    }
                    else
                    {
                        ISparqlAlgebra complex = bgp;

                        //If we contain an unplaced FILTER and we're not an OPTIONAL the FILTER
                        //applies here
                        return(new Filter(bgp, this.Filter));
                    }
                }
                else
                {
                    //We're not filtered (or all FILTERs were placed in the BGP) so we're just a BGP
                    return(bgp);
                }
            }
            else
            {
                //Create a basic BGP to start with
                ISparqlAlgebra complex = new Bgp();
                if (this._triplePatterns.Count > 0)
                {
                    complex = new Bgp(this._triplePatterns);
                }

                //Then Join each of the Graph Patterns as appropriate
                foreach (GraphPattern gp in this._graphPatterns)
                {
                    if (gp.IsGraph)
                    {
                        //A GRAPH clause means a Join of the current pattern to a Graph clause
                        complex = Join.CreateJoin(complex, new Algebra.Graph(gp.ToAlgebra(), gp.GraphSpecifier));
                    }
                    else if (gp.IsOptional)
                    {
                        if (gp.IsExists || gp.IsNotExists)
                        {
                            //An EXISTS/NOT EXISTS means an Exists Join of the current pattern to the EXISTS/NOT EXISTS clause
                            complex = new ExistsJoin(complex, gp.ToAlgebra(), gp.IsExists);
                        }
                        else
                        {
                            //An OPTIONAL means a Left Join of the current pattern to the OPTIONAL clause
                            //with a possible FILTER applied over the LeftJoin
                            if (gp.IsFiltered && gp.Filter != null)
                            {
                                //If the OPTIONAL clause has an unplaced FILTER it applies over the Left Join
                                complex = new LeftJoin(complex, gp.ToAlgebra(), gp.Filter);
                            }
                            else
                            {
                                complex = new LeftJoin(complex, gp.ToAlgebra());
                            }
                        }
                    }
                    else if (gp.IsMinus)
                    {
                        //Always introduce a Minus here even if the Minus is disjoint since during evaluation we'll choose
                        //not to execute it if it's disjoint
                        complex = new Minus(complex, gp.ToAlgebra());
                    }
                    else if (gp.IsService)
                    {
                        complex = Join.CreateJoin(complex, new Service(gp.GraphSpecifier, gp, gp.IsSilent));
                    }
                    else
                    {
                        //Otherwise we just join the pattern to the existing pattern
                        complex = Join.CreateJoin(complex, gp.ToAlgebra());
                    }
                }
                if (this._unplacedAssignments.Count > 0)
                {
                    //Unplaced assignments get Joined as a BGP here
                    complex = Join.CreateJoin(complex, new Bgp(this._unplacedAssignments));
                }
                if (this._isFiltered && (this._filter != null || this._unplacedFilters.Count > 0))
                {
                    if (this._isOptional && !(this._isExists || this._isNotExists))
                    {
                        //If there's an unplaced FILTER and we're an OPTIONAL then the FILTER will
                        //apply over the LeftJoin and is applied elsewhere in the Algebra transform
                        return(complex);
                    }
                    else
                    {
                        if (this._filter != null || this._unplacedFilters.Count > 0)
                        {
                            //If there's an unplaced FILTER and we're not an OPTIONAL pattern we apply
                            //the FILTER here
                            return(new Filter(complex, this.Filter));
                        }
                        else
                        {
                            return(complex);
                        }
                    }
                }
                else
                {
                    //If no FILTER just return the transform
                    return(complex);
                }
            }
        }
Example #8
0
        /// <summary>
        /// Optimises the Algebra so that BGPs containing relevant patterns are converted to use the <see cref="FullTextMatch">FullTextMatch</see> operator
        /// </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 <FullTextPattern> fps = FullTextHelper.ExtractPatterns(current.TriplePatterns);
                    if (fps.Count == 0)
                    {
                        return(algebra);
                    }
                    List <ITriplePattern> ps = current.TriplePatterns.ToList();

                    //First we want to find where each FullTextPattern is located in the original triple patterns
                    Dictionary <int, int> locations = new Dictionary <int, int>();
                    for (int i = 0; i < fps.Count; i++)
                    {
                        locations.Add(i, -1);
                        ITriplePattern first = fps[i].OriginalPatterns.First();
                        for (int j = 0; j < ps.Count; j++)
                        {
                            if (first.Equals(ps[j]))
                            {
                                locations[i] = j;
                                break;
                            }
                        }
                        //If we fail to locate this we've failed to optimise here so must abort
                        if (locations[i] == -1)
                        {
                            return(algebra);
                        }
                    }

                    //Knowing this we can then start splitting the BGP into several BGPs
                    int locBase = 0;
                    foreach (int i in Enumerable.Range(0, fps.Count).OrderBy(x => locations[x]).ToList())
                    {
                        //Wrap everything up to that point in a BGP excluding any patterns relevant to any FullTextPattern
                        result  = Join.CreateJoin(result, new Bgp(ps.Skip(locBase).Take(locations[i]).Where(tp => !(tp is TriplePattern) || !fps.Any(fp => fp.OriginalPatterns.Contains((TriplePattern)tp)))));
                        locBase = locations[i] + 1;
                        //Then apply the FullTextMatch operator over it
                        FullTextPattern ftp = fps[i];
                        result = new FullTextMatch(this._provider, result, ftp.MatchVariable, ftp.ScoreVariable, ftp.SearchTerm, ftp.Limit, ftp.ScoreThreshold);
                    }

                    //If there are any patterns left over remember to include them
                    if (locBase < ps.Count)
                    {
                        result = Join.CreateJoin(result, new Bgp(ps.Skip(locBase).Where(tp => !(tp is TriplePattern) || !fps.Any(fp => fp.OriginalPatterns.Contains((TriplePattern)tp)))));
                    }
                    return(result);

                    //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))
                    //    {
                    //        patterns.Add(ps[i]);
                    //    }
                    //    else
                    //    {
                    //        //Check to see if the Predicate of the Pattern match the Full Text Match Predicate URI
                    //        TriplePattern tp = (TriplePattern)ps[i];
                    //        PatternItem pred = tp.Predicate;
                    //        if (pred is NodeMatchPattern)
                    //        {
                    //            INode predNode = ((NodeMatchPattern)pred).Node;
                    //            if (predNode.NodeType == NodeType.Uri)
                    //            {
                    //                String predUri = ((IUriNode)predNode).Uri.ToString();
                    //                if (predUri.Equals(FullTextHelper.FullTextMatchPredicateUri))
                    //                {
                    //                    if (patterns.Count > 0) result = Join.CreateJoin(result, new Bgp(patterns));
                    //                    result = new FullTextMatch(this._provider, result, tp.Subject, tp.Object);
                    //                    patterns.Clear();
                    //                }
                    //                else
                    //                {
                    //                    patterns.Add(ps[i]);
                    //                }
                    //            }
                    //            else
                    //            {
                    //                patterns.Add(ps[i]);
                    //            }
                    //        }
                    //        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);
            }
        }