예제 #1
0
        public string ProcessBGP(Bgp bgp)
        {
            List <ITriplePattern> patterns = bgp.TriplePatterns.ToList();

            if (patterns.Count == 2)
            {
                TriplePattern p1     = patterns[0] as TriplePattern;
                TriplePattern p2     = patterns[1] as TriplePattern;
                MapNode       mNode1 = mapping.GetMapNodeForTripple(p1.Subject.ToString(), p1.Predicate.ToString(), p1.Object.ToString());
                MapNode       mNode2 = mapping.GetMapNodeForTripple(p2.Subject.ToString(), p2.Predicate.ToString(), p2.Object.ToString());
                //perform inner joins between them
                string sql1 = mapping.MergeSqlDBString(mNode1);
                string sql2 = mapping.MergeSqlDBString(mNode2);

                string sql = $"{InnerJoin(sql1, sql2)}";
                return(sql);
                //sql += $"{InnerJoin(patterns[0], patterns[1])}";
            }
            else if (patterns.Count == 1)
            {
                TriplePattern p          = patterns[0] as TriplePattern;
                MapNode       mNode      = mapping.GetMapNodeForTripple(p.Subject.ToString(), p.Predicate.ToString(), p.Object.ToString());
                string        sqlTripple = mapping.MergeSqlDBString(mNode);
                string        sql        = $"({sqlTripple})";
                return(sql);
            }
            else if (patterns.Count > 2)
            {
                //here we run the cyclic joins on each 2 queries,
                //optimizing the queries after each join
            }
            return(null);
        }
예제 #2
0
        private bool IsDisjointOperation(ISparqlAlgebra algebra, String lhsVar, String rhsVar, out int splitPoint)
        {
            splitPoint = -1;
            if (algebra is IBgp)
            {
                // Get Triple Patterns, can't split into a product if there are blank variables present
                List <ITriplePattern> ps = ((IBgp)algebra).TriplePatterns.ToList();
                if (ps.Any(p => !p.HasNoBlankVariables))
                {
                    return(false);
                }

                // Iterate over the Triple Patterns to see if we can split into a Product
                List <String> vars = new List <String>();
                for (int i = 0; i < ps.Count; i++)
                {
                    // Not a product if we've seen both variables already
                    if (vars.Contains(lhsVar) && vars.Contains(rhsVar))
                    {
                        return(false);
                    }

                    ITriplePattern p = ps[i];
                    switch (p.PatternType)
                    {
                    case TriplePatternType.Match:
                    case TriplePatternType.SubQuery:
                        if (vars.Count > 0 && vars.IsDisjoint(p.Variables))
                        {
                            // May be a filterable product if we've seen only one variable so far and have hit a point where a product occurs
                            if (vars.Contains(lhsVar) && !vars.Contains(rhsVar))
                            {
                                Bgp rhs = new Bgp(ps.Skip(i));
                                if (rhs.Variables.Contains(rhsVar))
                                {
                                    splitPoint = i;
                                    return(true);
                                }
                            }
                            else if (vars.Contains(rhsVar) && !vars.Contains(lhsVar))
                            {
                                Bgp rhs = new Bgp(ps.Skip(i));
                                if (rhs.Variables.Contains(lhsVar))
                                {
                                    splitPoint = i;
                                    return(true);
                                }
                            }
                        }
                        vars.AddRange(p.Variables);
                        break;

                    case TriplePatternType.BindAssignment:
                    case TriplePatternType.LetAssignment:
                        vars.Add(((IAssignmentPattern)p).VariableName);
                        break;

                    case TriplePatternType.Filter:
                        continue;

                    default:
                        // Can't determine if it is a disjoint operation if other pattern types are involved
                        return(false);
                    }
                }
                // If we get all the way here then not a product
                return(false);
            }
            else if (algebra is IJoin)
            {
                IJoin join = (IJoin)algebra;
                if (join.Lhs.Variables.IsDisjoint(join.Rhs.Variables))
                {
                    // There a product between the two sides of the join but are the two variables on different sides of that join
                    return(!(join.Lhs.Variables.Contains(lhsVar) && join.Lhs.Variables.Contains(rhsVar)) && !(join.Rhs.Variables.Contains(lhsVar) && join.Rhs.Variables.Contains(rhsVar)));
                }
                else
                {
                    return(false);
                }
            }
            else
            {
                return(false);
            }
        }
예제 #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);
            }
        }
예제 #4
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);
            }
        }
        /// <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);
            }
        }
예제 #6
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);
                }
            }
        }
예제 #7
0
        /// <summary>
        /// Processes SPARQL Algebra
        /// </summary>
        /// <param name="algebra">Algebra</param>
        /// <param name="context">SPARQL Evaluation Context</param>
        public string ProcessAlgebra(ISparqlAlgebra algebra)
        {
            string sql = "";

            if (algebra is IBgp) //a tripple pattern
            {
                //here use the value from mapping
                Bgp bgp = algebra as Bgp;

                //foreach(TriplePattern triplePattern in bgp.TriplePatterns)
                //{
                //    sql += this.mapping.GetMappingForTripple(triplePattern.Subject.ToString(), triplePattern.Predicate.ToString(), triplePattern.Object.ToString());
                //}
                List <ITriplePattern> patterns = bgp.TriplePatterns.ToList();
                if (patterns.Count >= 2)
                {
                    TriplePattern p1     = patterns[0] as TriplePattern;
                    TriplePattern p2     = patterns[1] as TriplePattern;
                    MapNode       mNode1 = mapping.GetMapNodeForTripple(p1.Subject.ToString(), p1.Predicate.ToString(), p1.Object.ToString());
                    MapNode       mNode2 = mapping.GetMapNodeForTripple(p2.Subject.ToString(), p2.Predicate.ToString(), p2.Object.ToString());
                    //perform inner joins between them
                    string sql1 = mapping.MergeSqlDBString(mNode1);
                    string sql2 = mapping.MergeSqlDBString(mNode2);

                    sql = $"{InnerJoin(sql1, sql2)}";
                    Console.WriteLine("\n\n{0}", sql);
                    //sql += $"{InnerJoin(patterns[0], patterns[1])}";
                }
                else
                {
                    sql += $"({patterns[0]})";
                }
            }
            else if (algebra is Select)
            {
                Select select    = algebra as Select;
                string variables = select.IsSelectAll ? "*" : string.Join(",", select.FixedVariables);
                string from      = ProcessAlgebra(select.InnerAlgebra);
                sql = $"SELECT {variables}\nFROM ({from}) \nWHERE *";
            }
            //else if (algebra is IFilter)
            //{
            //    return this.ProcessFilter((IFilter)algebra);
            //}
            ////else if (algebra is Algebra.Graph)
            ////{
            ////    return this.ProcessGraph((Algebra.Graph)algebra, context);
            ////}
            //else if (algebra is IJoin)
            //{
            //    return this.ProcessJoin((IJoin)algebra);
            //}
            //else if (algebra is ILeftJoin)
            //{
            //    return this.ProcessLeftJoin((ILeftJoin)algebra);
            //}

            //else if (algebra is IUnion)
            //{
            //    return this.ProcessUnion((IUnion)algebra);
            //}
            //else
            //{
            //    //Unknown Algebra
            //    throw new Exception("ProcessAlgebra(): Unknown algebra!");
            //}
            return(sql);
        }
예제 #8
0
        public void SparqlBgpEvaluation()
        {
            //Prepare the Store
            TripleStore store = new TripleStore();
            Graph       g     = new Graph();

            FileLoader.Load(g, "resources\\Turtle.ttl");
            store.Add(g);

            SparqlQueryParser parser     = new SparqlQueryParser();
            SparqlQuery       q          = parser.ParseFromString(@"PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT * WHERE {?s ?p ?o . ?s rdfs:label ?label}");
            Object            testResult = store.ExecuteQuery(q);

            ISparqlAlgebra testAlgebra = q.ToAlgebra();

            if (testResult is SparqlResultSet)
            {
                SparqlResultSet rset = (SparqlResultSet)testResult;
                Console.WriteLine(rset.Count + " Results");
                foreach (SparqlResult r in rset)
                {
                    Console.WriteLine(r.ToString());
                }
                Console.WriteLine();
            }

            //Create some Triple Patterns
            TriplePattern t1 = new TriplePattern(new VariablePattern("?s"), new VariablePattern("?p"), new VariablePattern("?o"));
            TriplePattern t2 = new TriplePattern(new VariablePattern("?s"), new NodeMatchPattern(g.CreateUriNode("rdfs:label")), new VariablePattern("?label"));
            TriplePattern t3 = new TriplePattern(new VariablePattern("?x"), new VariablePattern("?y"), new VariablePattern("?z"));
            TriplePattern t4 = new TriplePattern(new VariablePattern("?s"), new NodeMatchPattern(g.CreateUriNode(":name")), new VariablePattern("?name"));

            //Build some BGPs
            Bgp selectNothing  = new Bgp();
            Bgp selectAll      = new Bgp(t1);
            Bgp selectLabelled = new Bgp(new List <ITriplePattern>()
            {
                t1, t2
            });
            Bgp selectAllDisjoint = new Bgp(new List <ITriplePattern>()
            {
                t1, t3
            });
            Bgp selectLabels = new Bgp(t2);
            Bgp selectNames  = new Bgp(t4);
            //LeftJoin selectOptionalNamed = new LeftJoin(selectAll, new Optional(selectNames));
            LeftJoin selectOptionalNamed = new LeftJoin(selectAll, selectNames);
            Union    selectAllUnion      = new Union(selectAll, selectAll);
            Union    selectAllUnion2     = new Union(selectAllUnion, selectAll);
            Filter   selectAllUriObjects = new Filter(selectAll, new UnaryExpressionFilter(new IsUriFunction(new VariableTerm("o"))));

            //Test out the BGPs
            //Console.WriteLine("{}");
            //this.ShowMultiset(selectNothing.Evaluate(new SparqlEvaluationContext(null, store)));

            //Console.WriteLine("{?s ?p ?o}");
            //this.ShowMultiset(selectAll.Evaluate(new SparqlEvaluationContext(null, store)));

            //Console.WriteLine("{?s ?p ?o . ?s rdfs:label ?label}");
            //SparqlEvaluationContext context = new SparqlEvaluationContext(null, store);
            //this.ShowMultiset(selectLabelled.Evaluate(context));
            //SparqlResultSet lvnResult = new SparqlResultSet(context);

            //Console.WriteLine("{?s ?p ?o . ?x ?y ?z}");
            //this.ShowMultiset(selectAllDisjoint.Evaluate(new SparqlEvaluationContext(null, store)));

            //Console.WriteLine("{?s ?p ?o . OPTIONAL {?s :name ?name}}");
            //this.ShowMultiset(selectOptionalNamed.Evaluate(new SparqlEvaluationContext(null, store)));

            Console.WriteLine("{{?s ?p ?o} UNION {?s ?p ?o}}");
            this.ShowMultiset(selectAllUnion.Evaluate(new SparqlEvaluationContext(null, new InMemoryDataset(store))));

            Console.WriteLine("{{?s ?p ?o} UNION {?s ?p ?o} UNION {?s ?p ?o}}");
            this.ShowMultiset(selectAllUnion2.Evaluate(new SparqlEvaluationContext(null, new InMemoryDataset(store))));

            Console.WriteLine("{?s ?p ?o FILTER (ISURI(?o))}");
            this.ShowMultiset(selectAllUriObjects.Evaluate(new SparqlEvaluationContext(null, new InMemoryDataset(store))));
        }
예제 #9
0
        public void SparqlStreamingBgpSelectEvaluation()
        {
            //Get the Data we want to query
            TripleStore store = new TripleStore();
            Graph       g     = new Graph();

            FileLoader.Load(g, "resources\\InferenceTest.ttl");
            store.Add(g);
            //g = new Graph();
            //g.LoadFromFile("noise.ttl");
            //store.Add(g);

            Console.WriteLine(store.Triples.Count() + " Triples in Store");

            //Create the Triple Pattern we want to query with
            IUriNode fordFiesta = g.CreateUriNode(new Uri("http://example.org/vehicles/FordFiesta"));
            IUriNode rdfType    = g.CreateUriNode(new Uri(RdfSpecsHelper.RdfType));
            IUriNode rdfsLabel  = g.CreateUriNode(new Uri(NamespaceMapper.RDFS + "label"));
            IUriNode speed      = g.CreateUriNode(new Uri("http://example.org/vehicles/Speed"));
            IUriNode carClass   = g.CreateUriNode(new Uri("http://example.org/vehicles/Car"));

            TriplePattern allTriples            = new TriplePattern(new VariablePattern("?s"), new VariablePattern("?p"), new VariablePattern("?o"));
            TriplePattern allTriples2           = new TriplePattern(new VariablePattern("?x"), new VariablePattern("?y"), new VariablePattern("?z"));
            TriplePattern tp1                   = new TriplePattern(new VariablePattern("?s"), new NodeMatchPattern(rdfType), new NodeMatchPattern(carClass));
            TriplePattern tp2                   = new TriplePattern(new VariablePattern("?s"), new NodeMatchPattern(speed), new VariablePattern("?speed"));
            TriplePattern tp3                   = new TriplePattern(new VariablePattern("?s"), new NodeMatchPattern(rdfsLabel), new VariablePattern("?label"));
            TriplePattern novars                = new TriplePattern(new NodeMatchPattern(fordFiesta), new NodeMatchPattern(rdfType), new NodeMatchPattern(carClass));
            TriplePattern novars2               = new TriplePattern(new NodeMatchPattern(fordFiesta), new NodeMatchPattern(rdfsLabel), new NodeMatchPattern(carClass));
            FilterPattern blankSubject          = new FilterPattern(new UnaryExpressionFilter(new IsBlankFunction(new VariableTerm("?s"))));
            List <List <ITriplePattern> > tests = new List <List <ITriplePattern> >()
            {
                new List <ITriplePattern>()
                {
                },
                new List <ITriplePattern>()
                {
                    allTriples
                },
                new List <ITriplePattern>()
                {
                    allTriples, allTriples2
                },
                new List <ITriplePattern>()
                {
                    tp1
                },
                new List <ITriplePattern>()
                {
                    tp1, tp2
                },
                new List <ITriplePattern>()
                {
                    tp1, tp3
                },
                new List <ITriplePattern>()
                {
                    novars
                },
                new List <ITriplePattern>()
                {
                    novars, tp1
                },
                new List <ITriplePattern>()
                {
                    novars, tp1, tp2
                },
                new List <ITriplePattern>()
                {
                    novars2
                },
                new List <ITriplePattern>()
                {
                    tp1, blankSubject
                }
            };

            foreach (List <ITriplePattern> tps in tests)
            {
                Console.WriteLine(tps.Count + " Triple Patterns in the Query");
                foreach (ITriplePattern tp in tps)
                {
                    Console.WriteLine(tp.ToString());
                }
                Console.WriteLine();

                ISparqlAlgebra select          = new Bgp(tps);
                ISparqlAlgebra selectOptimised = new LazyBgp(tps, 10);

                //Evaluate with timings
                Stopwatch timer = new Stopwatch();
                TimeSpan  unopt, opt;
                timer.Start();
                BaseMultiset results1 = select.Evaluate(new SparqlEvaluationContext(null, new InMemoryDataset(store)));
                timer.Stop();
                unopt = timer.Elapsed;
                timer.Reset();
                timer.Start();
                BaseMultiset results2 = selectOptimised.Evaluate(new SparqlEvaluationContext(null, new InMemoryDataset(store)));
                timer.Stop();
                opt = timer.Elapsed;

                Console.WriteLine("SELECT = " + results1.GetType().ToString() + " (" + results1.Count + " Results) in " + unopt.ToString());
                Console.WriteLine("SELECT Optimised = " + results2.GetType().ToString() + " (" + results2.Count + " Results) in " + opt.ToString());

                Console.WriteLine();
                Console.WriteLine("Optimised Results");
                foreach (ISet s in results2.Sets)
                {
                    Console.WriteLine(s.ToString());
                }

                Assert.IsTrue(results1.Count >= results2.Count, "Optimised Select should have produced as many/fewer results than Unoptimised Select");

                Console.WriteLine();
            }
        }
예제 #10
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");
            }
        }
예제 #11
0
        /// <summary>
        /// Converts the Query into it's SPARQL Algebra representation (as represented in the Leviathan API)
        /// </summary>
        /// <returns></returns>
        public ISparqlAlgebra ToAlgebra()
        {
            //Firstly Transform the Root Graph Pattern to SPARQL Algebra
            ISparqlAlgebra pattern;

            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:
                        pattern = new SelectDistinctGraphs(this.Variables.First(v => v.IsResultVariable).Name);
                        break;

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

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

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

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

            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)
                {
                    pattern = this.ApplyAlgebraOptimisations(pattern);
                }

                //GROUP BY is the first thing applied
                if (this._groupBy != null)
                {
                    pattern = new GroupBy(pattern, this._groupBy);
                }

                //After grouping we do projection
                //This will generate the values for any Project Expressions and Aggregates
                pattern = new Project(pattern, this.Variables);

                //Add HAVING clause after the projection
                if (this._having != null)
                {
                    pattern = new Having(pattern, 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)
                {
                    pattern = new OrderBy(pattern, 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)
                {
                    pattern = new Select(pattern, this.Variables);
                }

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

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

                return(pattern);

            default:
                throw new RdfQueryException("Unable to convert unknown Query Types to SPARQL Algebra");
            }
        }
예제 #12
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);
        }
예제 #13
0
 private bool OptimiseBgp(Bgp bgp, out ISparqlAlgebra optimisedAlgebra)
 {
     if (bgp.TriplePatterns.OfType <FilterPattern>().Count() == 1)
     {
         var    filter = bgp.TriplePatterns.OfType <FilterPattern>().Select(fp => fp.Filter).First();
         string var;
         INode  term;
         bool   equals;
         if (IsIdentityExpression(filter.Expression, out var, out term, out @equals))
         {
             if (@equals)
             {
                 var triplePatterns = new List <ITriplePattern>();
                 foreach (var tp in bgp.TriplePatterns)
                 {
                     if (tp is FilterPattern)
                     {
                         continue;
                     }
                     if (tp is TriplePattern)
                     {
                         var triplePattern = (TriplePattern)tp;
                         if (triplePattern.Variables.Contains(var))
                         {
                             PatternItem subjPattern = triplePattern.Subject,
                                         predPattern = triplePattern.Predicate,
                                         objPattern  = triplePattern.Object;
                             if (var.Equals(triplePattern.Subject.VariableName))
                             {
                                 subjPattern = new NodeMatchPattern(term);
                             }
                             if (var.Equals(triplePattern.Predicate.VariableName))
                             {
                                 predPattern = new NodeMatchPattern(term);
                             }
                             if (var.Equals(triplePattern.Object.VariableName))
                             {
                                 objPattern = new NodeMatchPattern(term);
                             }
                             triplePatterns.Add(new TriplePattern(subjPattern, predPattern, objPattern));
                         }
                         else
                         {
                             triplePatterns.Add(triplePattern);
                         }
                     }
                     else
                     {
                         triplePatterns.Add(tp);
                     }
                 }
                 {
                     optimisedAlgebra = new Bgp(triplePatterns);
                     return(true);
                 }
             }
         }
     }
     optimisedAlgebra = bgp;
     return(false);
 }
예제 #14
0
        /// <summary>
        /// Evaluates the Triple Pattern in the given Context
        /// </summary>
        /// <param name="context">Context</param>
        /// <remarks>
        /// <para>
        /// Since a <see cref="FullTextPattern">FullTextPattern</see> on its own does not know how to execute itself as it would need a <see cref="VDS.RDF.Query.FullText.Search.IFullTextSearchProvider">IFullTextSearchProvider</see> it simply creates a BGP from the original patterns and they are evaluated as simple triple matches
        /// </para>
        /// </remarks>
        public override void Evaluate(SparqlEvaluationContext context)
        {
            Bgp bgp = new Bgp(this._origPatterns);

            context.Evaluate(bgp);
        }
예제 #15
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);
            }
        }
        /// <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);
            }
        }
예제 #17
0
        private bool IsDisjointOperation(ISparqlAlgebra algebra, List <String> filterVars, out int splitPoint)
        {
            splitPoint = -1;
            if (algebra is IBgp)
            {
                // Get Triple Patterns, can't split into a product if there are blank variables present
                List <ITriplePattern> ps = ((IBgp)algebra).TriplePatterns.ToList();
                if (ps.Any(p => !p.HasNoBlankVariables))
                {
                    return(false);
                }

                // Iterate over the Triple Patterns to see if we can split into a Product
                List <String> vars = new List <String>();
                for (int i = 0; i < ps.Count; i++)
                {
                    // Not a product if we've seen both variables already
                    if (filterVars.All(v => vars.Contains(v)))
                    {
                        return(false);
                    }

                    ITriplePattern p = ps[i];
                    if (p.PatternType == TriplePatternType.Match || p.PatternType == TriplePatternType.SubQuery)
                    {
                        if (vars.Count > 0 && vars.IsDisjoint(p.Variables))
                        {
                            // Is a filterable product if we've not seen all the variables so far and have hit a point where a product occurs
                            // and all the variables are not in the RHS
                            Bgp rhs = new Bgp(ps.Skip(i));
                            if (!filterVars.All(v => rhs.Variables.Contains(v)))
                            {
                                splitPoint = i;
                                return(true);
                            }
                        }
                        vars.AddRange(p.Variables);
                    }
                    else if (p.PatternType == TriplePatternType.BindAssignment || p.PatternType == TriplePatternType.LetAssignment)
                    {
                        vars.Add(((IAssignmentPattern)p).VariableName);
                    }
                    else if (p.PatternType == TriplePatternType.Filter)
                    {
                        continue;
                    }
                    else
                    {
                        return(false);
                    }
                }
                // If we get all the way here then not a product
                return(false);
            }
            else if (algebra is IJoin)
            {
                IJoin join = (IJoin)algebra;
                if (join.Lhs.Variables.IsDisjoint(join.Rhs.Variables))
                {
                    // There a product between the two sides of the join but are the variables spead over different sides of that join?
                    // If all variables occur on one side then this is not a filtered product
                    return(!filterVars.All(v => join.Lhs.Variables.Contains(v)) && !filterVars.All(v => join.Rhs.Variables.Contains(v)));
                }
                else
                {
                    return(false);
                }
            }
            else
            {
                return(false);
            }
        }
예제 #18
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);
            }
        }