Skip to content

Commit 16dd1e8

Browse files
Eric Prud'hommeauxclaude
andcommitted
+ BNodeResolver: told-bnode emulation over the SPARQL protocol
SPARQL 1.0 rejected "told bnodes" (mentioning a blank node received in an earlier response). Emulate them: for each SELECT, associate every response bnode with a minimal, uniqueness-verified fragment of in/out arcs found by instrumenting the query with interrogation round trips, recursing through neighbor bnodes when ground arcs do not discriminate. Fragments intern to stable proxy terms; mentioning a proxy in a later query expands to a fresh variable constrained by its fragment. Ambiguous pins (N indistinguishable candidates) resolve all candidates and assign response labels bijectively. RemoteGraphProvider materializes triple-pattern fetches into a local BGP with subsumption, so interrogation results answer later neighborhood queries. Wired into ShEx validation (Validator::NeighborhoodSource) and Algae 3 remote execution (Engine::remote fault-in at bgpmatch, attach via Engine::attachClientFactory). RelabelingLocalClient test double relabels response bnodes per response so label-luck code fails. Deferred: bnodes emerging from grouped aggregates (the flagship query never joins bnodes across an aggregation). tests: proxy stability across relabeled responses; mention() rejoining the right membership; cache subsumption; ShEx remote==local parity; evidence-dnf remote==local golden. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 105030e commit 16dd1e8

8 files changed

Lines changed: 798 additions & 3 deletions

File tree

‎CMakeLists.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ add_library(SWObjects STATIC
168168
lib/ShExManifest.cpp
169169
lib/ShExMap.cpp
170170
lib/Algae3.cpp
171+
lib/BNodeResolver.cpp
171172
lib/SWObjects.cpp
172173
${SWOBJ_GENERATED_SOURCES}
173174
)

‎lib/Algae3.cpp‎

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
*/
1818

1919
#include "Algae3.hpp"
20+
#include "BNodeResolver.hpp"
2021
#include "TurtleParser.hpp"
2122

2223
#include <algorithm>
@@ -26,6 +27,8 @@
2627
namespace w3c_sw {
2728
namespace a3 {
2829

30+
bnr::SPARQLClient* (*Engine::attachClientFactory) (const std::string&, AtomFactory*) = NULL;
31+
2932
const std::vector<const Result*>* Engine::currentGroup = NULL;
3033
const std::map<const Result*, ProofSet>* Engine::currentProofs = NULL;
3134
const RdfDB* Engine::currentDB = NULL;
@@ -89,7 +92,15 @@ namespace a3 {
8992
rs = new ResultSet(atomFactory); // the unit result set
9093
}
9194

92-
Engine::~Engine () { delete rs; }
95+
Engine::~Engine () {
96+
delete rs;
97+
for (std::vector<bnr::RemoteGraphProvider*>::const_iterator it = ownedProviders.begin();
98+
it != ownedProviders.end(); ++it)
99+
delete *it;
100+
for (std::vector<bnr::SPARQLClient*>::const_iterator it = ownedClients.begin();
101+
it != ownedClients.end(); ++it)
102+
delete *it;
103+
}
93104

94105
ResultSet* Engine::unitRS () const { return new ResultSet(atomFactory); }
95106

@@ -222,6 +233,8 @@ namespace a3 {
222233
const TTerm* s = lookup(tp->getS());
223234
const TTerm* p = lookup(tp->getP());
224235
const TTerm* o = lookup(tp->getO());
236+
if (e.remote != NULL)
237+
e.remote->ensurePattern(s, p, o); // remote fault-in (told bnodes expand)
225238
const BasicGraphPattern::triple_iterator end;
226239
for (BasicGraphPattern::triple_iterator ti = graph->getTripleIterator(s, p, o);
227240
ti != end; ++ti) {
@@ -652,8 +665,16 @@ namespace a3 {
652665
}
653666

654667
virtual void visit (const Attach& a) {
655-
throw std::string("attach (external database \"") + a.name
656-
+ "\") is parsed for Algae2 compatibility but not evaluable here";
668+
if (Engine::attachClientFactory == NULL)
669+
throw std::string("attach (external database \"") + a.name
670+
+ "\"): no SPARQL client factory registered";
671+
bnr::SPARQLClient* client
672+
= Engine::attachClientFactory(a.driver->getLexicalValue(), e.atomFactory);
673+
e.ownedClients.push_back(client);
674+
bnr::RemoteGraphProvider* provider = new bnr::RemoteGraphProvider(
675+
e.atomFactory, client, e.db.ensureGraph(DefaultGraph));
676+
e.ownedProviders.push_back(provider);
677+
e.remote = provider;
657678
}
658679

659680
virtual void visit (const Ask& a) { e.ask(*a.pattern); }

‎lib/Algae3.hpp‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <vector>
2424

2525
namespace w3c_sw {
26+
namespace bnr { class RemoteGraphProvider; struct SPARQLClient; }
2627
namespace a3 {
2728

2829
enum EvalMode { EVAL_topdown, EVAL_bottomup };
@@ -336,6 +337,17 @@ namespace a3 {
336337
bool lastTest; // set by `test`
337338
std::string baseDir; // directory for resolving load paths
338339

340+
/** remote execution: when set, bgpmatch faults each substituted
341+
* triple pattern through the provider (told-bnode seeds expand to
342+
* their identifying fragments) before matching the local cache */
343+
bnr::RemoteGraphProvider* remote = NULL; // borrowed unless via attach
344+
/** `attach <endpoint> name` creates a provider over a client from
345+
* this factory (tests inject a local relabeling double) */
346+
static bnr::SPARQLClient* (*attachClientFactory) (const std::string& iri,
347+
AtomFactory* atomFactory);
348+
std::vector<bnr::SPARQLClient*> ownedClients; // from attach
349+
std::vector<bnr::RemoteGraphProvider*> ownedProviders;
350+
339351
/** rows are sw::Results inside an sw::ResultSet (so sw::Expression
340352
* evaluation applies natively); proofs keyed by row pointer. */
341353
ResultSet* rs; // owned

0 commit comments

Comments
 (0)