/// <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)); }
/// <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); } }
/// <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)); }
/// <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"); } }
/// <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 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); } }
/// <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); } }
/// <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); } }
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); } } }
/// <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); } }