示例#1
0
 /// <summary>
 /// Processes a BGP
 /// </summary>
 /// <param name="bgp">BGP</param>
 /// <param name="context">SPARQL Evaluation Context</param>
 public virtual BaseMultiset ProcessBgp(IBgp bgp, SparqlEvaluationContext context)
 {
     if (context == null)
     {
         context = this.GetContext();
     }
     return(bgp.Evaluate(context));
 }
示例#2
0
        /// <summary>
        /// Optimises the Algebra to use implict joins where applicable
        /// </summary>
        /// <param name="algebra">Algebra</param>
        /// <returns></returns>
        public ISparqlAlgebra Optimise(ISparqlAlgebra algebra)
        {
            try
            {
                if (algebra is Filter)
                {
                    Filter f = (Filter)algebra;

                    // See if the Filtered Product style optimization applies instead
                    int splitPoint = -1;
                    if (f.SparqlFilter.Expression.CanParallelise && IsDisjointOperation(f.InnerAlgebra, f.SparqlFilter.Expression.Variables.ToList(), out splitPoint))
                    {
                        if (splitPoint > -1)
                        {
                            // Means the inner algebra is a BGP we can split into two parts
                            IBgp bgp = (IBgp)f.InnerAlgebra;
                            return(new FilteredProduct(new Bgp(bgp.TriplePatterns.Take(splitPoint)), new Bgp(bgp.TriplePatterns.Skip(splitPoint)), f.SparqlFilter.Expression));
                        }
                        else
                        {
                            // Means that the inner algebra is a Join where the sides are disjoint
                            IJoin join = (IJoin)f.InnerAlgebra;
                            return(new FilteredProduct(join.Lhs, join.Rhs, f.SparqlFilter.Expression));
                        }
                    }
                    else
                    {
                        return(f.Transform(this));
                    }
                }
                else if (algebra is IAbstractJoin)
                {
                    return(((IAbstractJoin)algebra).Transform(this));
                }
                else if (algebra is IUnaryOperator)
                {
                    return(((IUnaryOperator)algebra).Transform(this));
                }
                else
                {
                    return(algebra);
                }
            }
            catch
            {
                return(algebra);
            }
        }
示例#3
0
 /// <summary>
 /// Processes a BGP.
 /// </summary>
 /// <param name="bgp">BGP.</param>
 /// <param name="context">SPARQL Evaluation Context.</param>
 public override BaseMultiset ProcessBgp(IBgp bgp, SparqlEvaluationContext context)
 {
     return(ExplainAndEvaluate <IBgp>(bgp, context, base.ProcessBgp));
 }
示例#4
0
        /// <summary>
        /// Prints BGP Analysis.
        /// </summary>
        /// <param name="bgp">Analysis.</param>
        private void PrintBgpAnalysis(IBgp bgp)
        {
            if (!HasFlag(ExplanationLevel.AnalyseBgps))
            {
                return;
            }

            List <ITriplePattern> ps = bgp.TriplePatterns.ToList();

            if (ps.Count == 0)
            {
                PrintExplanations("Empty BGP");
            }
            else
            {
                HashSet <String> vars = new HashSet <string>();
                for (int i = 0; i < ps.Count; i++)
                {
                    StringBuilder output = new StringBuilder();

                    // Print what will happen
                    if (ps[i].PatternType == TriplePatternType.Filter)
                    {
                        output.Append("Apply ");
                    }
                    else if (ps[i].PatternType == TriplePatternType.BindAssignment || ps[i].PatternType == TriplePatternType.LetAssignment)
                    {
                        output.Append("Extend by Assignment with ");
                    }
                    else if (ps[i].PatternType == TriplePatternType.SubQuery)
                    {
                        output.Append("Sub-query ");
                    }
                    else if (ps[i].PatternType == TriplePatternType.Path)
                    {
                        output.Append("Property Path ");
                    }
                    else if (ps[i].PatternType == TriplePatternType.PropertyFunction)
                    {
                        output.Append("Property Function ");
                    }

                    // Print the type of Join to be performed
                    if (i > 0 && (ps[i].PatternType == TriplePatternType.Match || ps[i].PatternType == TriplePatternType.SubQuery || ps[i].PatternType == TriplePatternType.Path))
                    {
                        if (vars.IsDisjoint <String>(ps[i].Variables))
                        {
                            output.Append("Cross Product with ");
                        }
                        else
                        {
                            List <String> joinVars = vars.Intersect <String>(ps[i].Variables).ToList();
                            output.Append("Join on {");
                            joinVars.ForEach(v => output.Append(" ?" + v + ","));
                            output.Remove(output.Length - 1, 1);
                            output.Append(" } with ");
                        }
                    }

                    // Print the actual Triple Pattern
                    output.Append(_formatter.Format(ps[i]));

                    // Update variables seen so far unless a FILTER which cannot introduce new variables
                    if (ps[i].PatternType != TriplePatternType.Filter)
                    {
                        foreach (String var in ps[i].Variables)
                        {
                            vars.Add(var);
                        }
                    }

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

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

                // Do variable substitution on the patterns
                List <ITriplePattern> ps = new List <ITriplePattern>();
                foreach (ITriplePattern p in bgp.TriplePatterns)
                {
                    switch (p.PatternType)
                    {
                    case TriplePatternType.Match:
                        IMatchTriplePattern tp   = (IMatchTriplePattern)p;
                        PatternItem         subj = tp.Subject.VariableName != null && tp.Subject.VariableName.Equals(this._findVar) ? this._replaceItem : tp.Subject;
                        if (ReferenceEquals(subj, this._replaceItem))
                        {
                            canReplaceObjects = (this._canReplaceCustom ? this._canReplaceObjects : true);
                        }
                        PatternItem pred = tp.Predicate.VariableName != null && tp.Predicate.VariableName.Equals(this._findVar) ? this._replaceItem : tp.Predicate;
                        if (ReferenceEquals(pred, this._replaceItem))
                        {
                            canReplaceObjects = (this._canReplaceCustom ? this._canReplaceObjects : true);
                        }
                        PatternItem obj = tp.Object.VariableName != null && tp.Object.VariableName.Equals(this._findVar) ? this._replaceItem : tp.Object;
                        if (ReferenceEquals(obj, this._replaceItem) && !canReplaceObjects)
                        {
                            throw new Exception("Unable to substitute a variable into the object position in this scope");
                        }
                        ps.Add(new TriplePattern(subj, pred, obj));
                        break;

                    case TriplePatternType.Filter:
                        IFilterPattern fp = (IFilterPattern)p;
                        ps.Add(new FilterPattern(new UnaryExpressionFilter(this.Transform(fp.Filter.Expression))));
                        break;

                    case TriplePatternType.BindAssignment:
                        IAssignmentPattern bp = (IAssignmentPattern)p;
                        ps.Add(new BindPattern(bp.VariableName, this.Transform(bp.AssignExpression)));
                        break;

                    case TriplePatternType.LetAssignment:
                        IAssignmentPattern lp = (IAssignmentPattern)p;
                        ps.Add(new LetPattern(lp.VariableName, this.Transform(lp.AssignExpression)));
                        break;

                    case TriplePatternType.SubQuery:
                        throw new RdfQueryException("Cannot do variable substitution when a sub-query is present");

                    case TriplePatternType.Path:
                        throw new RdfQueryException("Cannot do variable substitution when a property path is present");

                    case TriplePatternType.PropertyFunction:
                        throw new RdfQueryException("Cannot do variable substituion when a property function is present");

                    default:
                        throw new RdfQueryException("Cannot do variable substitution on unknown triple patterns");
                    }
                }
                return(new Bgp(ps));
            }
            else if (algebra is Service)
            {
                throw new RdfQueryException("Cannot do variable substitution when a SERVICE clause is present");
            }
            else if (algebra is SubQuery)
            {
                throw new RdfQueryException("Cannot do variable substitution when a sub-query is present");
            }
            else if (algebra is IPathOperator)
            {
                throw new RdfQueryException("Cannot do variable substitution when a property path is present");
            }
            else if (algebra is Algebra.Graph)
            {
                Algebra.Graph g = (Algebra.Graph)((IUnaryOperator)algebra).Transform(this);
                if (g.GraphSpecifier is VariableToken && g.GraphSpecifier.Value.Equals("?" + this._findVar))
                {
                    if (this._replaceToken != null)
                    {
                        return(new Algebra.Graph(g.InnerAlgebra, this._replaceToken));
                    }
                    else
                    {
                        throw new RdfQueryException("Cannot do a variable substitution when the variable is used for a GRAPH specifier and the replacement term is not a URI");
                    }
                }
                else
                {
                    return(g);
                }
            }
            else if (algebra is IUnaryOperator)
            {
                return(((IUnaryOperator)algebra).Transform(this));
            }
            else if (algebra is IAbstractJoin)
            {
                return(((IAbstractJoin)algebra).Transform(this));
            }
            else if (algebra is ITerminalOperator)
            {
                return(algebra);
            }
            else
            {
                throw new RdfQueryException("Cannot do variable substitution on unknown algebra");
            }
        }
示例#6
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);
            }
        }
示例#7
0
 /// <summary>
 /// Optimises the Algebra to use implict joins where applicable
 /// </summary>
 /// <param name="algebra">Algebra</param>
 /// <returns></returns>
 public ISparqlAlgebra Optimise(ISparqlAlgebra algebra)
 {
     try
     {
         if (algebra is Filter)
         {
             Filter f = (Filter)algebra;
             String lhsVar, rhsVar;
             bool   equals;
             if (IsImplicitJoinExpression(f.SparqlFilter.Expression, out lhsVar, out rhsVar, out equals))
             {
                 // We must ensure that both variables are in scope
                 List <String> vars = f.InnerAlgebra.Variables.ToList();
                 if (vars.Contains(lhsVar) && vars.Contains(rhsVar))
                 {
                     try
                     {
                         // Try to use the extend style optimization
                         VariableSubstitutionTransformer transformer = new VariableSubstitutionTransformer(rhsVar, lhsVar);
                         if (!equals || Options.UnsafeOptimisation)
                         {
                             transformer.CanReplaceObjects = true;
                         }
                         ISparqlAlgebra extAlgebra = transformer.Optimise(f.InnerAlgebra);
                         return(new Extend(extAlgebra, new VariableTerm(lhsVar), rhsVar));
                     }
                     catch
                     {
                         // See if the Filtered Product style optimization applies instead
                         int splitPoint = -1;
                         if (IsDisjointOperation(f.InnerAlgebra, lhsVar, rhsVar, out splitPoint))
                         {
                             if (splitPoint > -1)
                             {
                                 // Means the inner algebra is a BGP we can split into two parts
                                 IBgp bgp = (IBgp)f.InnerAlgebra;
                                 return(new FilteredProduct(new Bgp(bgp.TriplePatterns.Take(splitPoint)), new Bgp(bgp.TriplePatterns.Skip(splitPoint)), f.SparqlFilter.Expression));
                             }
                             else
                             {
                                 // Means that the inner algebra is a Join where the sides are disjoint
                                 IJoin join = (IJoin)f.InnerAlgebra;
                                 return(new FilteredProduct(join.Lhs, join.Rhs, f.SparqlFilter.Expression));
                             }
                         }
                         else
                         {
                             return(f.Transform(this));
                         }
                     }
                 }
                 else
                 {
                     return(f.Transform(this));
                 }
             }
             else
             {
                 return(f.Transform(this));
             }
         }
         else if (algebra is IAbstractJoin)
         {
             return(((IAbstractJoin)algebra).Transform(this));
         }
         else if (algebra is IUnaryOperator)
         {
             return(((IUnaryOperator)algebra).Transform(this));
         }
         else
         {
             return(algebra);
         }
     }
     catch
     {
         return(algebra);
     }
 }
示例#8
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);
            }
        }
示例#10
0
        /// <summary>
        /// Optimises the algebra to include property functions
        /// </summary>
        /// <param name="algebra">Algebra</param>
        /// <returns></returns>
        public ISparqlAlgebra Optimise(ISparqlAlgebra algebra)
        {
            if (algebra is IBgp)
            {
                IBgp current = (IBgp)algebra;
                if (current.PatternCount == 0)
                {
                    return(current);
                }

                List <ITriplePattern>           ps        = current.TriplePatterns.ToList();
                List <IPropertyFunctionPattern> propFuncs = PropertyFunctionHelper.ExtractPatterns(ps, _factories.Value);
                if (propFuncs.Count == 0)
                {
                    return(current);
                }

                // Remove raw Triple Patterns pertaining to extracted property functions
                foreach (IPropertyFunctionPattern propFunc in propFuncs)
                {
                    // Track where we need to insert the property function back into the BGP
                    ITriplePattern first        = propFunc.OriginalPatterns.First();
                    int            origLocation = ps.FindIndex(p => p.Equals(first));
                    foreach (ITriplePattern tp in propFunc.OriginalPatterns)
                    {
                        int location = ps.FindIndex(p => p.Equals(tp));
                        if (location >= 0)
                        {
                            if (location < origLocation)
                            {
                                origLocation--;
                            }
                            ps.RemoveAt(location);
                        }
                        else
                        {
                            throw new RdfQueryException("Bad Property Function extraction");
                        }
                    }

                    // Make the insert
                    if (origLocation >= ps.Count || origLocation < 0 || ps.Count == 0)
                    {
                        ps.Add(propFunc);
                    }
                    else
                    {
                        ps.Insert(origLocation, propFunc);
                    }
                }

                // Return a new BGP
                return(new Bgp(ps));
            }
            else if (algebra is ITerminalOperator)
            {
                return(algebra);
            }
            else if (algebra is IAbstractJoin)
            {
                return(((IAbstractJoin)algebra).Transform(this));
            }
            else if (algebra is IUnaryOperator)
            {
                return(((IUnaryOperator)algebra).Transform(this));
            }
            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);
            }
        }
示例#12
0
        public static void ResolveBGPsFromDB(ISparqlAlgebra algebra, IGraph g, Dictionary <string, string> dbURIs)
        {
            if (algebra is IBgp)
            {
                IBgp bgp = algebra as IBgp;
                //do work here

                /*
                 *  resolve DB name from subj/predicate/obj
                 *  resolve Table name
                 *  make query
                 *  convert results to rdf triples
                 *  add all the triples to IGraph g
                 */
                var triples = bgp.TriplePatterns;

                foreach (TriplePattern triple in triples)
                {
                    //do work here for each triple

                    string subjConnString = GetConnStringFromURI(dbURIs, triple.Subject.ToString());
                    string predConnString = GetConnStringFromURI(dbURIs, triple.Predicate.ToString());
                    string objConnString  = GetConnStringFromURI(dbURIs, triple.Object.ToString());

                    if (subjConnString == null && predConnString == null && objConnString == null)
                    {
                        //we deal with request to FEDERATED schema or it's an error
                        //if it's FEDERATED schema, we should find subclasses/subproperties, equivalent classes/properties and query for them

                        if (triple.Subject.VariableName == null) //is not a pattern
                        {
                            //IN FEDERATED schema there're no individuals, so we can't have subject URI or subject literal here!

                            //subject here could not be a URI! it would be logically incorrect!!!!!
                            //it could only be a pattern

                            throw new InvalidOperationException("Subject variable in tripple, referring to FEDERATED schema should be a PATTERN!");
                            //throw new NotImplementedException();
                        }
                        if (triple.Predicate.VariableName == null) //is not a pattern
                        {
                            //query for equivalent properties
                            TripleStore store = new TripleStore();
                            store.Add(g);

                            SparqlParameterizedString queryString = new SparqlParameterizedString();

                            queryString.Namespaces.AddNamespace("owl", new Uri("http://www.w3.org/2002/07/owl#"));
                            queryString.CommandText = @"SELECT ?property1 WHERE {
                                                        ?property owl:equivalentProperty ?property1
                                                        filter regex(str(?property), '^" + triple.Predicate.ToString().Trim('<', '>') + "')}";

                            SparqlQueryParser parser = new SparqlQueryParser();
                            SparqlQuery       query  = parser.ParseFromString(queryString.ToString());

                            ISparqlQueryProcessor processor = new LeviathanQueryProcessor(store);   //process query
                            var results = processor.ProcessQuery(query) as SparqlResultSet;
                            Console.WriteLine();

                            //object can be a literal or a pattern
                            foreach (SparqlResult resultPredicate in results)
                            {
                                //query with new predicates and transform the results to FEDERATED schema syntax
                                queryString             = new SparqlParameterizedString();
                                queryString.CommandText = $"SELECT * WHERE {{ ?subj <{resultPredicate[0].ToString()}> {triple.Object.ToString()} }} ";
                                SparqlResultSet resultSet = QuerySparqlFromDB(g, queryString, dbURIs);

                                string federatedStem = triple.Predicate.ToString().Trim('<', '>').Split('#')[0]; //left part (before '#') -> /FEDERATED/table name
                                //federatedStem += '/'; // /FEDERATED/table name/

                                foreach (SparqlResult result in resultSet)
                                {
                                    Dictionary <string, string> dbInfo = GetDatabaseInfoForIndividualURI(result[0].ToString());
                                    string subjStr = $"{federatedStem}/{dbInfo["dbName"]}.{dbInfo["columnName"]}.{dbInfo["columnValue"]}";
                                    string predStr = triple.Predicate.ToString().Trim('<', '>');
                                    string objStr;
                                    if (triple.Object.VariableName == null) //not a pattern
                                    {
                                        objStr = triple.Object.ToString().Trim('"');
                                    }
                                    else //object was a pattern ?object in sparql query
                                    {
                                        //dbInfo = GetDatabaseInfoForIndividualURI(result[1].ToString());
                                        if (IsLiteralValue(result[1].ToString()))
                                        {
                                            objStr = result[1].ToString();
                                        }
                                        else
                                        {
                                            dbInfo = GetDatabaseInfoForIndividualURI(result[1].ToString());
                                            objStr = $"{federatedStem}/{dbInfo["dbName"]}.{dbInfo["columnName"]}.{dbInfo["columnValue"]}";
                                        }
                                    }
                                    INode subj = g.CreateUriNode(new Uri(subjStr));
                                    INode pred = g.CreateUriNode(new Uri(predStr));
                                    INode obj; // = g.CreateLiteralNode($"{rawTriple.Obj}");
                                    if (IsLiteralValue(objStr))
                                    {
                                        obj = g.CreateLiteralNode(objStr);
                                    }
                                    else
                                    {
                                        obj = g.CreateUriNode(new Uri(objStr));
                                    }
                                    g.Assert(new Triple(subj, pred, obj));
                                }
                            }


                            //throw new NotImplementedException();
                        }
                        if (triple.Object.VariableName == null) //is not a pattern
                        {
                            if (!IsLiteralValue(triple.Object.ToString()))
                            {
                                throw new InvalidOperationException("Object variable in tripple, referring to FEDERATED schema should be a PATTERN!");
                                //throw new NotImplementedException();
                            }
                        }
                        //throw new NotImplementedException();
                    }

                    if (subjConnString != null) //most probably, subjectConnString will be NULL (cause subject may be a pattern)
                    {
                        //TODO
                        //if subj is not a literal, we should query DB for subj triples!!!
                        //<http://www.semanticweb.org/LMS/User/ID.1> <http://www.semanticweb.org/LMS/User#NAME> ?name

                        //<subject> <predicate> ?object

                        /*
                         *  SELECT User.NAME
                         *  FROM table(subject)
                         *  WHERE User.ID=1 AND User.NAME IS NOT NULL
                         */

                        //<subject> ?predicate ?object

                        /*
                         *  SELECT *
                         *  FROM table(subject)
                         *  WHERE User.ID=1
                         */

                        //<subject> ?predicate "Object"

                        /*
                         *  SELECT *
                         *  FROM table(subject)
                         *  WHERE User.ID=1
                         *  //check for "Object" inside DataReader, when queried
                         */

                        DBLoader dbLoader = new DBLoader(subjConnString);
                        Dictionary <string, string> dbInfo = GetDatabaseInfoForIndividualURI(triple.Subject.ToString());

                        List <RawTriple> rawTriples = dbLoader.GetTriplesForSubject(
                            tableName: dbInfo["tableName"],
                            individualColName: dbInfo["columnName"],
                            individualColValue: dbInfo["columnValue"],
                            prefixURI: dbInfo["prefix"],
                            predicateColName: triple.Predicate.VariableName == null ? GetPrefixDbNameTableNameColNameFromURI(triple.Predicate.ToString())["columnName"] : null,
                            obj: triple.Object.VariableName == null ? triple.Object.ToString().Trim('>', '<') : null
                            );
                        foreach (var rawTriple in rawTriples)
                        {
                            INode subj = g.CreateUriNode(new Uri(rawTriple.Subj));
                            INode pred = g.CreateUriNode(new Uri(rawTriple.Pred));
                            INode obj  = g.CreateLiteralNode($"{rawTriple.Obj}");
                            g.Assert(new Triple(subj, pred, obj));
                        }
                    }
                    if (predConnString != null)
                    {
                        //referring to DataType- or Object- Property
                        if (triple.Object.VariableName == null) //object is not a pattern
                        {
                            if (IsLiteralValue(triple.Object.ToString()))
                            {
                                // ?s <predicate> "Object"

                                /*
                                 *  SELECT *
                                 *  FROM table(predicate)
                                 *  WHERE table.Attribute="Object"
                                 */
                                DBLoader dbLoader = new DBLoader(predConnString);
                                Dictionary <string, string> dbInfo     = GetPrefixDbNameTableNameColNameFromURI(triple.Predicate.ToString());
                                List <RawTriple>            rawTriples = dbLoader.GetTriplesForPredicateObject(
                                    tableName: dbInfo["tableName"],
                                    columnName: dbInfo["columnName"],
                                    prefixURI: dbInfo["prefix"],
                                    obj: triple.Object.ToString());
                                foreach (var rawTriple in rawTriples)
                                {
                                    INode subj = g.CreateUriNode(new Uri(rawTriple.Subj));
                                    INode pred = g.CreateUriNode(new Uri(rawTriple.Pred));
                                    INode obj  = g.CreateLiteralNode($"{rawTriple.Obj}");
                                    g.Assert(new Triple(subj, pred, obj));
                                }
                            }
                            else if (objConnString != null)
                            {
                                // ?s <predicate> <object>
                                throw new NotImplementedException();
                            }
                        }
                        else //object is a pattern
                        {
                            //?s <predicate> ?object

                            /*
                             *  SELECT *
                             *  FROM table(predicate)
                             *  WHERE table.Attribute="Object"
                             */
                            DBLoader dbLoader = new DBLoader(predConnString);
                            Dictionary <string, string> dbInfo     = GetPrefixDbNameTableNameColNameFromURI(triple.Predicate.ToString());
                            List <RawTriple>            rawTriples = dbLoader.GetTriplesForPredicateObject(
                                tableName: dbInfo["tableName"],
                                columnName: dbInfo["columnName"],
                                prefixURI: dbInfo["prefix"],
                                obj: null);
                            foreach (var rawTriple in rawTriples)
                            {
                                INode subj = g.CreateUriNode(new Uri(rawTriple.Subj));
                                INode pred = g.CreateUriNode(new Uri(rawTriple.Pred));
                                INode obj  = g.CreateLiteralNode($"{rawTriple.Obj}");
                                g.Assert(new Triple(subj, pred, obj));
                            }
                        }
                    }
                    if (objConnString != null) //object is not a pattern
                    {
                        //TODO
                        throw new NotImplementedException();
                    }

                    //check if subj, pred and obj refer to one DB
                }
            }
            else
            {
                if (algebra is IUnaryOperator)
                {
                    algebra = algebra as IUnaryOperator;
                    ResolveBGPsFromDB((algebra as IUnaryOperator).InnerAlgebra, g, dbURIs);
                }
                else if (algebra is IAbstractJoin)
                {
                    ResolveBGPsFromDB((algebra as IAbstractJoin).Lhs, g, dbURIs);
                    ResolveBGPsFromDB((algebra as IAbstractJoin).Rhs, g, dbURIs);
                }
            }
        }
示例#13
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);
            }
        }