public static void FindMSG(SelectableSource store, Entity node, Store msg) { if (node.Uri != null) { throw new ArgumentException("node must be anonymous"); } ResSet nodesSeen = new ResSet(); ResSet nodesToAdd = new ResSet(); nodesToAdd.Add(node); while (nodesToAdd.Count > 0) { ResSet nodes = nodesToAdd; nodesToAdd = new ResSet(); Sink sink = new Sink(msg, nodesToAdd); foreach (Entity n in nodes) { if (nodesSeen.Contains(n)) { continue; } nodesSeen.Add(n); store.Select(new Statement(n, null, null, null), sink); store.Select(new Statement(null, n, null, null), sink); store.Select(new Statement(null, null, n, null), sink); } } }
public void Select(Statement template, StatementSink sink) { if (!selectresults.ContainsKey(template)) { MemoryStore s = new MemoryStore(); source.Select(template, s); selectresults[template] = s; } ((MemoryStore)selectresults[template]).Select(sink); }
public static Statement?SelectSingle(this SelectableSource src, Statement tpl) { var sink = new FirstStatementSink(); src.Select(tpl, sink); return(sink.First); }
public static Statement?SelectSingle(this SelectableSource src, SelectFilter filter) { var sink = new FirstStatementSink(); src.Select(filter, sink); return(sink.First); }
public static IList <Statement> SelectList(this SelectableSource src, SelectFilter filter, bool distinct, int maxStatements) { var sink = new StatementListSink(distinct, maxStatements); src.Select(filter, sink); return(sink.List); }
public static bool DefaultContains(SelectableSource source, Statement template) { StatementExistsSink sink = new StatementExistsSink(); SelectFilter filter = new SelectFilter(template); filter.Limit = 1; source.Select(filter, sink); return(sink.Exists); }
// This method finds all minimal self-contained graphs // by painting nodes colors (the colors happen to be // objects) in one pass over the statements and then doing // a second pass to put each statement mentioning a bnode // into the appropriate graph structure. public static Graph[] FindMSGs(SelectableSource source, bool loadIntoMemory) { FindMSGsSink sink = new FindMSGsSink(source, loadIntoMemory); source.Select(Statement.All, sink); ArrayList graphs = new ArrayList(sink.colors.Keys); return((Graph[])graphs.ToArray(typeof(Graph))); }
public void Select(StatementSink s) { if (statements == null) { source.Select(Statement.All, new Sink(this, s)); } else { statements.Select(s); } }
public static void DefaultSelect(SelectableSource source, SelectFilter filter, StatementSink sink) { // This method should be avoided... if (filter.LiteralFilters != null) { sink = new SemWeb.Filters.FilterSink(filter.LiteralFilters, sink, source); } foreach (Entity subject in filter.Subjects == null ? new Entity[] { null } : filter.Subjects) { foreach (Entity predicate in filter.Predicates == null ? new Entity[] { null } : filter.Predicates) { foreach (Resource objct in filter.Objects == null ? new Resource[] { null } : filter.Objects) { foreach (Entity meta in filter.Metas == null ? new Entity[] { null } : filter.Metas) { source.Select(new Statement(subject, predicate, objct, meta), sink); } } } } }
public static bool DefaultContains(SelectableSource source, Statement template) { StatementExistsSink sink = new StatementExistsSink(); SelectFilter filter = new SelectFilter(template); filter.Limit = 1; source.Select(filter, sink); return sink.Exists; }
public override void Select(SelectFilter filter, SelectableSource data, StatementSink sink) { if (filter.Predicates == null || filter.LiteralFilters != null) { data.Select(filter, sink); return; } ResSet remainingPredicates = new ResSet(); Entity[] subjects = filter.Subjects; Entity[] predicates = filter.Predicates; Resource[] objects = filter.Objects; Entity[] metas = filter.Metas; foreach (Entity p in predicates) { if (p == type) { if (objects != null) { // Do the subjects have any of the types listed in the objects, // or what things have those types? // Expand objects by the subclass closure of the objects data.Select(new SelectFilter(subjects, new Entity[] { p }, GetClosure(objects, subclasses, true), metas), sink); // Process domains and ranges. ResSet dom = new ResSet(), ran = new ResSet(); Hashtable domPropToType = new Hashtable(); Hashtable ranPropToType = new Hashtable(); foreach (Entity e in GetClosure(objects, subclasses, true)) { Entity[] dc = GetClosure((ResSet)domainof[e], subprops, true); if (dc != null) foreach (Entity c in dc) { dom.Add(c); AddRelation(c, e, domPropToType); } dc = GetClosure((ResSet)rangeof[e], subprops, true); if (dc != null) foreach (Entity c in dc) { ran.Add(c); AddRelation(c, e, ranPropToType); } } // If it's in the domain of any of these properties, // we know its type. Only do this if subjects are given, // since otherwise we have to select for all of the values // of all of these properties, and that doesn't scale well. if (subjects != null) { if (dom.Count > 0) data.Select(new SelectFilter(subjects, dom.ToEntityArray(), null, metas), new ExpandDomRan(0, domPropToType, sink)); if (ran.Count > 0) data.Select(new SelectFilter(null, ran.ToEntityArray(), subjects, metas), new ExpandDomRan(1, ranPropToType, sink)); } } else if (subjects != null) { // What types do these subjects have? // Expand the resulting types by the closure of their superclasses data.Select(new SelectFilter(subjects, new Entity[] { p }, objects, metas), new Expand(superclasses, sink)); // Use domains and ranges to get type info data.Select(new SelectFilter(subjects, null, null, metas), new Expand3(0, domains, superclasses, sink)); data.Select(new SelectFilter(null, null, subjects, metas), new Expand3(1, ranges, superclasses, sink)); } else { // What has type what? We won't answer that question. data.Select(filter, sink); } } else if ((p == subClassOf || p == subPropertyOf) && (metas == null || metas[0] == Statement.DefaultMeta)) { Hashtable supers = (p == subClassOf) ? superclasses : superprops; Hashtable subs = (p == subClassOf) ? subclasses : subprops; if (subjects != null && objects != null) { // Expand objects by the subs closure of the objects. data.Select(new SelectFilter(subjects, new Entity[] { p }, GetClosure(objects, subs, true), metas), sink); } else if (subjects != null) { // get all of the supers of all of the subjects foreach (Entity s in subjects) foreach (Entity o in GetClosure(s, supers, false)) sink.Add(new Statement(s, p, o)); } else if (objects != null) { // get all of the subs of all of the objects foreach (Resource o in objects) { if (o is Literal) continue; foreach (Entity s in GetClosure((Entity)o, subs, false)) sink.Add(new Statement(s, p, (Entity)o)); } } else { // What is a subclass/property of what? We won't answer that. data.Select(filter, sink); } } else { remainingPredicates.Add(p); } } if (remainingPredicates.Count > 0) { // Also query the subproperties of any property // being queried, but remember which subproperties // came from which superproperties so we can map them // back to the properties actually queried. The closures // contain the queried properties themselves too. ResSet qprops = new ResSet(); Hashtable propfrom = new Hashtable(); foreach (Entity p in remainingPredicates) { foreach (Entity sp in GetClosure(p, subprops, true)) { AddRelation(sp, p, propfrom); qprops.Add(sp); } } //data.Select(subjects, qprops.ToEntityArray(), objects, metas, new LiteralDTMap(ranges, new PredMap(propfrom, sink))); SelectFilter sf = new SelectFilter(subjects, qprops.ToEntityArray(), objects, metas); sf.LiteralFilters = filter.LiteralFilters; sf.Limit = filter.Limit; data.Select(sf, new PredMap(propfrom, sink)); } }
public void Select(Statement template, StatementSink sink) { output.WriteLine("SELECT: " + template); source.Select(template, sink); }
public override void Select(SelectFilter filter, SelectableSource data, StatementSink sink) { if (filter.Predicates == null || filter.LiteralFilters != null) { data.Select(filter, sink); return; } ResSet remainingPredicates = new ResSet(); Entity[] subjects = filter.Subjects; Entity[] predicates = filter.Predicates; Resource[] objects = filter.Objects; Entity[] metas = filter.Metas; foreach (Entity p in predicates) { if (p == type) { if (objects != null) { // Do the subjects have any of the types listed in the objects, // or what things have those types? // Expand objects by the subclass closure of the objects data.Select(new SelectFilter(subjects, new Entity[] { p }, GetClosure(objects, subclasses, true), metas), sink); // Process domains and ranges. ResSet dom = new ResSet(), ran = new ResSet(); Hashtable domPropToType = new Hashtable(); Hashtable ranPropToType = new Hashtable(); foreach (Entity e in GetClosure(objects, subclasses, true)) { Entity[] dc = GetClosure((ResSet)domainof[e], subprops, true); if (dc != null) { foreach (Entity c in dc) { dom.Add(c); AddRelation(c, e, domPropToType); } } dc = GetClosure((ResSet)rangeof[e], subprops, true); if (dc != null) { foreach (Entity c in dc) { ran.Add(c); AddRelation(c, e, ranPropToType); } } } // If it's in the domain of any of these properties, // we know its type. Only do this if subjects are given, // since otherwise we have to select for all of the values // of all of these properties, and that doesn't scale well. if (subjects != null) { if (dom.Count > 0) { data.Select(new SelectFilter(subjects, dom.ToEntityArray(), null, metas), new ExpandDomRan(0, domPropToType, sink)); } if (ran.Count > 0) { data.Select(new SelectFilter(null, ran.ToEntityArray(), subjects, metas), new ExpandDomRan(1, ranPropToType, sink)); } } } else if (subjects != null) { // What types do these subjects have? // Expand the resulting types by the closure of their superclasses data.Select(new SelectFilter(subjects, new Entity[] { p }, objects, metas), new Expand(superclasses, sink)); // Use domains and ranges to get type info data.Select(new SelectFilter(subjects, null, null, metas), new Expand3(0, domains, superclasses, sink)); data.Select(new SelectFilter(null, null, subjects, metas), new Expand3(1, ranges, superclasses, sink)); } else { // What has type what? We won't answer that question. data.Select(filter, sink); } } else if ((p == subClassOf || p == subPropertyOf) && (metas == null || metas[0] == Statement.DefaultMeta)) { Hashtable supers = (p == subClassOf) ? superclasses : superprops; Hashtable subs = (p == subClassOf) ? subclasses : subprops; if (subjects != null && objects != null) { // Expand objects by the subs closure of the objects. data.Select(new SelectFilter(subjects, new Entity[] { p }, GetClosure(objects, subs, true), metas), sink); } else if (subjects != null) { // get all of the supers of all of the subjects foreach (Entity s in subjects) { foreach (Entity o in GetClosure(s, supers, false)) { sink.Add(new Statement(s, p, o)); } } } else if (objects != null) { // get all of the subs of all of the objects foreach (Resource o in objects) { if (o is Literal) { continue; } foreach (Entity s in GetClosure((Entity)o, subs, false)) { sink.Add(new Statement(s, p, (Entity)o)); } } } else { // What is a subclass/property of what? We won't answer that. data.Select(filter, sink); } } else { remainingPredicates.Add(p); } } if (remainingPredicates.Count > 0) { // Also query the subproperties of any property // being queried, but remember which subproperties // came from which superproperties so we can map them // back to the properties actually queried. The closures // contain the queried properties themselves too. ResSet qprops = new ResSet(); Hashtable propfrom = new Hashtable(); foreach (Entity p in remainingPredicates) { foreach (Entity sp in GetClosure(p, subprops, true)) { AddRelation(sp, p, propfrom); qprops.Add(sp); } } //data.Select(subjects, qprops.ToEntityArray(), objects, metas, new LiteralDTMap(ranges, new PredMap(propfrom, sink))); SelectFilter sf = new SelectFilter(subjects, qprops.ToEntityArray(), objects, metas); sf.LiteralFilters = filter.LiteralFilters; sf.Limit = filter.Limit; data.Select(sf, new PredMap(propfrom, sink)); } }
private bool Query(int groupindex, BindingSet bindings, SelectableSource targetModel) { QueryStatement[] group = statements[groupindex]; QueryStatement qs = group[0]; int numMultiplyBound = IsMultiplyBound(qs.Subject, bindings) + IsMultiplyBound(qs.Predicate, bindings) + IsMultiplyBound(qs.Object, bindings); if (numMultiplyBound >= 1) { // If there is one or more multiply-bound variable, // then we need to iterate through the permutations // of the variables in the statement. Debug(qs.ToString() + " Something Multiply Bound"); MemoryStore matches = new MemoryStore(); targetModel.Select( new SelectFilter( (Entity[])qs.Subject.GetValues(bindings.Union, true), (Entity[])qs.Predicate.GetValues(bindings.Union, true), qs.Object.GetValues(bindings.Union, false), QueryMeta == null ? null : new Entity[] { QueryMeta } ), new ClearMetaDupCheck(matches)); Debug("\t" + matches.StatementCount + " Matches"); if (matches.StatementCount == 0) { // This statement doesn't match any of // the existing bindings. If this was // optional, preserve the bindings. return qs.Optional; } // We need to preserve the pairings of // the multiply bound variable with the matching // statements. ArrayList newbindings = new ArrayList(); if (!qs.Optional) bindings.Union.Clear(qs); foreach (QueryResult binding in bindings.Results) { // Break apart the permutations in this binding. BindingEnumerator enumer2 = new BindingEnumerator(qs, binding); Entity s, p; Resource o; while (enumer2.MoveNext(out s, out p, out o)) { // Get the matching statements from the union query Statement bs = new Statement(s, p, o); MemoryStore innermatches = matches.Select(bs).Load(); // If no matches, the binding didn't match the filter. if (innermatches.StatementCount == 0) { if (qs.Optional) { // Preserve the binding. QueryResult bc = binding.Clone(); bc.Set(qs, bs); newbindings.Add(bc); continue; } else { // Toss out the binding. continue; } } for (int si = 0; si < innermatches.StatementCount; si++) { Statement m = innermatches[si]; if (!MatchesFilters(m, qs, targetModel)) { if (qs.Optional) { QueryResult bc = binding.Clone(); bc.Set(qs, bs); newbindings.Add(bc); } continue; } bindings.Union.Add(qs, m); QueryResult r = binding.Clone(); r.Set(qs, m); r.StatementMatched[groupindex] = true; newbindings.Add(r); } } } bindings.Results = newbindings; } else { // There are no multiply bound variables, but if // there are more than two unbound variables, // we need to be sure to preserve the pairings // of the matching values. int numUnbound = IsUnbound(qs.Subject, bindings) + IsUnbound(qs.Predicate, bindings) + IsUnbound(qs.Object, bindings); bool sunbound = IsUnbound(qs.Subject, bindings) == 1; bool punbound = IsUnbound(qs.Predicate, bindings) == 1; bool ounbound = IsUnbound(qs.Object, bindings) == 1; Statement s = GetStatement(qs, bindings); // If we couldn't get a statement out of this, // then if this was not an optional filter, // fail. If this was optional, don't change // the bindings any. if (s == StatementFailed) return qs.Optional; if (numUnbound == 0) { Debug(qs.ToString() + " All bound"); // All variables are singly bound already. // We can just test if the statement exists. if (targetModel.Contains(s)) { // Mark each binding that it matched this statement. foreach (QueryResult r in bindings.Results) r.StatementMatched[groupindex] = true; } else { return qs.Optional; } } else if (numUnbound == 1) { Debug(qs.ToString() + " 1 Unbound"); // There is just one unbound variable. The others // are not multiply bound, so they must be uniquely // bound (but they may not be bound in all results). // Run a combined select to find all possible values // of the unbound variable at once, and set these to // be the values of the variable for matching results. ResSet values = new ResSet(); MemoryStore ms = new MemoryStore(); targetModel.Select(s, ms); for (int si = 0; si < ms.StatementCount; si++) { Statement match = ms[si]; if (!MatchesFilters(match, qs, targetModel)) continue; if (sunbound) values.Add(match.Subject); if (punbound) values.Add(match.Predicate); if (ounbound) values.Add(match.Object); } Debug("\t" + values.Count + " matches"); if (values.Count == 0) return qs.Optional; int varIndex = -1; if (sunbound) varIndex = qs.Subject.VarIndex; if (punbound) varIndex = qs.Predicate.VarIndex; if (ounbound) varIndex = qs.Object.VarIndex; if (bindings.Results.Count == 0) bindings.Results.Add(new QueryResult(this)); bindings.Union.Bindings[varIndex] = new ResSet(); foreach (Resource r in values) bindings.Union.Bindings[varIndex].Add(r); foreach (QueryResult r in bindings.Results) { // Check that the bound variables are bound in this result. // If it is bound, it will be bound to the correct resource, // but it might not be bound at all if an optional statement // failed to match -- in which case, don't modify the binding. if (qs.Subject.IsVariable && !sunbound && r.Bindings[qs.Subject.VarIndex] == null) continue; if (qs.Predicate.IsVariable && !punbound && r.Bindings[qs.Predicate.VarIndex] == null) continue; if (qs.Object.IsVariable && !ounbound && r.Bindings[qs.Object.VarIndex] == null) continue; r.Bindings[varIndex] = values; r.StatementMatched[groupindex] = true; } } else { // There are two or more unbound variables, the // third variable being uniquely bound, if bound. // Keep track of the pairing of unbound variables. if (numUnbound == 3) throw new QueryExecutionException("Query would select all statements in the store."); Debug(qs.ToString() + " 2 or 3 Unbound"); if (bindings.Results.Count == 0) bindings.Results.Add(new QueryResult(this)); ArrayList newbindings = new ArrayList(); MemoryStore ms = new MemoryStore(); targetModel.Select(s, ms); for (int si = 0; si < ms.StatementCount; si++) { Statement match = ms[si]; if (!MatchesFilters(match, qs, targetModel)) continue; bindings.Union.Add(qs, match); foreach (QueryResult r in bindings.Results) { if (numUnbound == 2) { // Check that the bound variable is bound in this result. // If it is bound, it will be bound to the correct resource, // but it might not be bound at all if an optional statement // failed to match -- in which case, preserve the binding if // this was an optional statement. bool matches = true; if (qs.Subject.IsVariable && !sunbound && r.Bindings[qs.Subject.VarIndex] == null) matches = false; if (qs.Predicate.IsVariable && !punbound && r.Bindings[qs.Predicate.VarIndex] == null) matches = false; if (qs.Object.IsVariable && !ounbound && r.Bindings[qs.Object.VarIndex] == null) matches = false; if (!matches) { if (qs.Optional) newbindings.Add(r); continue; } } QueryResult r2 = r.Clone(); r2.Add(qs, match); r2.StatementMatched[groupindex] = true; newbindings.Add(r2); } } if (newbindings.Count == 0) return qs.Optional; // don't clear out bindings if this was optional and it failed bindings.Results = newbindings; } } return true; }
public static void query (SelectableSource source, Statement filter) { using (RdfWriter writer = new N3Writer (System.Console.Out)) source.Select (filter, writer); }
public override void Select(SelectFilter filter, SelectableSource targetModel, StatementSink sink) { targetModel.Select(filter, sink); }
private StatementIterator GetIterator(Entity[] subjects, Entity[] predicates, Resource[] objects, Entity[] metas, java.util.List litFilters, bool defaultGraph) { DateTime start = DateTime.Now; if (subjects == null && predicates == null && objects == null) { throw new QueryExecutionException("Query would select all statements in the store."); } if (subjects != null) { Depersist(subjects); } if (predicates != null) { Depersist(predicates); } if (objects != null) { Depersist(objects); } if (metas != null) { Depersist(metas); } if (subjects != null && subjects.Length == 0) { return(new StatementIterator(null)); } if (predicates != null && predicates.Length == 0) { return(new StatementIterator(null)); } if (objects != null && objects.Length == 0) { return(new StatementIterator(null)); } if (metas != null && metas.Length == 0) { return(new StatementIterator(null)); } MemoryStore results = new MemoryStore(); StatementSink sink = results; if (!source.Distinct) { sink = new SemWeb.Util.DistinctStatementsSink(results, defaultGraph && metas == null); } SelectFilter filter = new SelectFilter(subjects, predicates, objects, metas); if (litFilters != null) { filter.LiteralFilters = new LiteralFilter[litFilters.size()]; for (int i = 0; i < litFilters.size(); i++) { filter.LiteralFilters[i] = (LiteralFilter)litFilters.get(i); } } source.Select(filter, sink); Log("SELECT: " + filter + " => " + results.StatementCount + " statements [" + (DateTime.Now - start) + "s]"); return(new StatementIterator(results.ToArray())); }
public static void DefaultSelect(SelectableSource source, SelectFilter filter, StatementSink sink) { // This method should be avoided... if (filter.LiteralFilters != null) sink = new SemWeb.Filters.FilterSink(filter.LiteralFilters, sink, source); foreach (Entity subject in filter.Subjects == null ? new Entity[] { null } : filter.Subjects) foreach (Entity predicate in filter.Predicates == null ? new Entity[] { null } : filter.Predicates) foreach (Resource objct in filter.Objects == null ? new Resource[] { null } : filter.Objects) foreach (Entity meta in filter.Metas == null ? new Entity[] { null } : filter.Metas) source.Select(new Statement(subject, predicate, objct, meta), sink); }
public static void FindMSG(SelectableSource store, Entity node, StatementSink msg) { if (node.Uri != null) throw new ArgumentException("node must be anonymous"); ResSet nodesSeen = new ResSet(); ResSet nodesToAdd = new ResSet(); nodesToAdd.Add(node); while (nodesToAdd.Count > 0) { ResSet nodes = nodesToAdd; nodesToAdd = new ResSet(); Sink sink = new Sink(msg, nodesToAdd); foreach (Entity n in nodes) { if (nodesSeen.Contains(n)) continue; nodesSeen.Add(n); store.Select(new Statement(n, null, null, null), sink); store.Select(new Statement(null, n, null, null), sink); store.Select(new Statement(null, null, n, null), sink); } } }
public static void query(SelectableSource source, Statement filter) { using (RdfWriter writer = new N3Writer(System.Console.Out)) source.Select(filter, writer); }
// This method finds all minimal self-contained graphs // by painting nodes colors (the colors happen to be // objects) in one pass over the statements and then doing // a second pass to put each statement mentioning a bnode // into the appropriate graph structure. public static Graph[] FindMSGs(SelectableSource source, bool loadIntoMemory) { FindMSGsSink sink = new FindMSGsSink(source, loadIntoMemory); source.Select(Statement.All, sink); ArrayList graphs = new ArrayList(sink.colors.Keys); return (Graph[])graphs.ToArray(typeof(Graph)); }
private bool Query(int groupindex, BindingSet bindings, SelectableSource targetModel) { QueryStatement[] group = statements[groupindex]; QueryStatement qs = group[0]; int numMultiplyBound = IsMultiplyBound(qs.Subject, bindings) + IsMultiplyBound(qs.Predicate, bindings) + IsMultiplyBound(qs.Object, bindings); if (numMultiplyBound >= 1) { // If there is one or more multiply-bound variable, // then we need to iterate through the permutations // of the variables in the statement. Debug(qs.ToString() + " Something Multiply Bound"); MemoryStore matches = new MemoryStore(); targetModel.Select( new SelectFilter( (Entity[])qs.Subject.GetValues(bindings.Union, true), (Entity[])qs.Predicate.GetValues(bindings.Union, true), qs.Object.GetValues(bindings.Union, false), QueryMeta == null ? null : new Entity[] { QueryMeta } ), new ClearMetaDupCheck(matches)); Debug("\t" + matches.StatementCount + " Matches"); if (matches.StatementCount == 0) { // This statement doesn't match any of // the existing bindings. If this was // optional, preserve the bindings. return(qs.Optional); } // We need to preserve the pairings of // the multiply bound variable with the matching // statements. ArrayList newbindings = new ArrayList(); if (!qs.Optional) { bindings.Union.Clear(qs); } foreach (QueryResult binding in bindings.Results) { // Break apart the permutations in this binding. BindingEnumerator enumer2 = new BindingEnumerator(qs, binding); Entity s, p; Resource o; while (enumer2.MoveNext(out s, out p, out o)) { // Get the matching statements from the union query Statement bs = new Statement(s, p, o); MemoryStore innermatches = matches.Select(bs).Load(); // If no matches, the binding didn't match the filter. if (innermatches.StatementCount == 0) { if (qs.Optional) { // Preserve the binding. QueryResult bc = binding.Clone(); bc.Set(qs, bs); newbindings.Add(bc); continue; } else { // Toss out the binding. continue; } } for (int si = 0; si < innermatches.StatementCount; si++) { Statement m = innermatches[si]; if (!MatchesFilters(m, qs, targetModel)) { if (qs.Optional) { QueryResult bc = binding.Clone(); bc.Set(qs, bs); newbindings.Add(bc); } continue; } bindings.Union.Add(qs, m); QueryResult r = binding.Clone(); r.Set(qs, m); r.StatementMatched[groupindex] = true; newbindings.Add(r); } } } bindings.Results = newbindings; } else { // There are no multiply bound variables, but if // there are more than two unbound variables, // we need to be sure to preserve the pairings // of the matching values. int numUnbound = IsUnbound(qs.Subject, bindings) + IsUnbound(qs.Predicate, bindings) + IsUnbound(qs.Object, bindings); bool sunbound = IsUnbound(qs.Subject, bindings) == 1; bool punbound = IsUnbound(qs.Predicate, bindings) == 1; bool ounbound = IsUnbound(qs.Object, bindings) == 1; Statement s = GetStatement(qs, bindings); // If we couldn't get a statement out of this, // then if this was not an optional filter, // fail. If this was optional, don't change // the bindings any. if (s == StatementFailed) { return(qs.Optional); } if (numUnbound == 0) { Debug(qs.ToString() + " All bound"); // All variables are singly bound already. // We can just test if the statement exists. if (targetModel.Contains(s)) { // Mark each binding that it matched this statement. foreach (QueryResult r in bindings.Results) { r.StatementMatched[groupindex] = true; } } else { return(qs.Optional); } } else if (numUnbound == 1) { Debug(qs.ToString() + " 1 Unbound"); // There is just one unbound variable. The others // are not multiply bound, so they must be uniquely // bound (but they may not be bound in all results). // Run a combined select to find all possible values // of the unbound variable at once, and set these to // be the values of the variable for matching results. ResSet values = new ResSet(); MemoryStore ms = new MemoryStore(); targetModel.Select(s, ms); for (int si = 0; si < ms.StatementCount; si++) { Statement match = ms[si]; if (!MatchesFilters(match, qs, targetModel)) { continue; } if (sunbound) { values.Add(match.Subject); } if (punbound) { values.Add(match.Predicate); } if (ounbound) { values.Add(match.Object); } } Debug("\t" + values.Count + " matches"); if (values.Count == 0) { return(qs.Optional); } int varIndex = -1; if (sunbound) { varIndex = qs.Subject.VarIndex; } if (punbound) { varIndex = qs.Predicate.VarIndex; } if (ounbound) { varIndex = qs.Object.VarIndex; } if (bindings.Results.Count == 0) { bindings.Results.Add(new QueryResult(this)); } bindings.Union.Bindings[varIndex] = new ResSet(); foreach (Resource r in values) { bindings.Union.Bindings[varIndex].Add(r); } foreach (QueryResult r in bindings.Results) { // Check that the bound variables are bound in this result. // If it is bound, it will be bound to the correct resource, // but it might not be bound at all if an optional statement // failed to match -- in which case, don't modify the binding. if (qs.Subject.IsVariable && !sunbound && r.Bindings[qs.Subject.VarIndex] == null) { continue; } if (qs.Predicate.IsVariable && !punbound && r.Bindings[qs.Predicate.VarIndex] == null) { continue; } if (qs.Object.IsVariable && !ounbound && r.Bindings[qs.Object.VarIndex] == null) { continue; } r.Bindings[varIndex] = values; r.StatementMatched[groupindex] = true; } } else { // There are two or more unbound variables, the // third variable being uniquely bound, if bound. // Keep track of the pairing of unbound variables. if (numUnbound == 3) { throw new QueryExecutionException("Query would select all statements in the store."); } Debug(qs.ToString() + " 2 or 3 Unbound"); if (bindings.Results.Count == 0) { bindings.Results.Add(new QueryResult(this)); } ArrayList newbindings = new ArrayList(); MemoryStore ms = new MemoryStore(); targetModel.Select(s, ms); for (int si = 0; si < ms.StatementCount; si++) { Statement match = ms[si]; if (!MatchesFilters(match, qs, targetModel)) { continue; } bindings.Union.Add(qs, match); foreach (QueryResult r in bindings.Results) { if (numUnbound == 2) { // Check that the bound variable is bound in this result. // If it is bound, it will be bound to the correct resource, // but it might not be bound at all if an optional statement // failed to match -- in which case, preserve the binding if // this was an optional statement. bool matches = true; if (qs.Subject.IsVariable && !sunbound && r.Bindings[qs.Subject.VarIndex] == null) { matches = false; } if (qs.Predicate.IsVariable && !punbound && r.Bindings[qs.Predicate.VarIndex] == null) { matches = false; } if (qs.Object.IsVariable && !ounbound && r.Bindings[qs.Object.VarIndex] == null) { matches = false; } if (!matches) { if (qs.Optional) { newbindings.Add(r); } continue; } } QueryResult r2 = r.Clone(); r2.Add(qs, match); r2.StatementMatched[groupindex] = true; newbindings.Add(r2); } } if (newbindings.Count == 0) { return(qs.Optional); // don't clear out bindings if this was optional and it failed } bindings.Results = newbindings; } } return(true); }