select query working for current triple setup and tests

feat/orm-diffs
Laurin Weger 13 hours ago
parent 0753859d0d
commit b8f14ed561
No known key found for this signature in database
GPG Key ID: 9B372BB0B792770F
  1. 16
      engine/verifier/src/orm/initialize.rs
  2. 1
      engine/verifier/src/orm/process_changes.rs
  3. 207
      engine/verifier/src/orm/query.rs
  4. 19
      sdk/rust/src/local_broker.rs
  5. 47
      sdk/rust/src/tests/orm_creation.rs

@ -84,8 +84,12 @@ impl Verifier {
shape_type: &OrmShapeType, shape_type: &OrmShapeType,
) -> Result<Value, NgError> { ) -> Result<Value, NgError> {
// Query triples for this shape // Query triples for this shape
let shape_query = shape_type_to_sparql_select(&shape_type.schema, &shape_type.shape, None)?; let shape_triples = self.query_quads_for_shape_type(
let shape_triples = self.query_sparql_select(shape_query, Some(nuri_to_string(nuri)))?; Some(nuri_to_string(nuri)),
&shape_type.schema,
&shape_type.shape,
None,
)?;
let changes: OrmChanges = let changes: OrmChanges =
self.apply_triple_changes(&shape_triples, &[], nuri, Some(session_id.clone()), true)?; self.apply_triple_changes(&shape_triples, &[], nuri, Some(session_id.clone()), true)?;
@ -220,9 +224,15 @@ pub(crate) fn materialize_orm_object(
} }
orm_obj_map.insert(property_name.clone(), Value::Object(nested_objects_map)); orm_obj_map.insert(property_name.clone(), Value::Object(nested_objects_map));
} else { } else {
if let Some(BasicType::Str(object_iri)) = pred_change.values_added.get(0) { // Pick the first valid nested object among the added values.
// There may be multiple values (extras), but for single-cardinality
// predicates we materialize just one valid nested object.
for val in &pred_change.values_added {
if let BasicType::Str(object_iri) = val {
if let Some(nested_orm_obj) = get_nested_orm_obj(object_iri) { if let Some(nested_orm_obj) = get_nested_orm_obj(object_iri) {
orm_obj_map.insert(property_name.clone(), nested_orm_obj); orm_obj_map.insert(property_name.clone(), nested_orm_obj);
break;
}
} }
} }
} }

@ -357,6 +357,7 @@ impl Verifier {
&schema, &schema,
&shape_iri, &shape_iri,
Some(objects_to_fetch), Some(objects_to_fetch),
None,
)?; )?;
let new_triples = let new_triples =
self.query_sparql_select(shape_query, Some(nuri_to_string(nuri)))?; self.query_sparql_select(shape_query, Some(nuri_to_string(nuri)))?;

@ -23,6 +23,31 @@ use ng_repo::errors::NgError;
use ng_repo::log::*; use ng_repo::log::*;
impl Verifier { impl Verifier {
pub fn query_quads_for_shape_type(
&self,
nuri: Option<String>,
schema: &OrmSchema,
shape: &ShapeIri,
filter_subjects: Option<Vec<String>>,
) -> Result<Vec<Triple>, NgError> {
// If nuri is present and it is not the whole graph (did:ng:i), use limit_to_graph.
let limit_to_graph = match nuri {
Some(nuri) => {
if nuri == "did:ng:i" {
None
} else {
Some(nuri)
}
}
None => None,
};
let select_query =
shape_type_to_sparql_select(schema, shape, filter_subjects, limit_to_graph)?;
return self.query_sparql_select(select_query, None);
}
pub fn query_sparql_select( pub fn query_sparql_select(
&self, &self,
query: String, query: String,
@ -30,11 +55,12 @@ impl Verifier {
) -> Result<Vec<Triple>, NgError> { ) -> Result<Vec<Triple>, NgError> {
let oxistore = self.graph_dataset.as_ref().unwrap(); let oxistore = self.graph_dataset.as_ref().unwrap();
let nuri_str = nuri.as_ref().map(|s| s.as_str()); // Log base IRI safely even when None
log_debug!("querying select\n{}\n{}\n", nuri_str.unwrap(), query); let nuri_dbg = nuri.as_deref().unwrap_or("");
log_debug!("querying select\n{}\n{}\n", nuri_dbg, query);
let parsed = let parsed = Query::parse(&query, nuri.as_deref())
Query::parse(&query, nuri_str).map_err(|e| NgError::OxiGraphError(e.to_string()))?; .map_err(|e| NgError::OxiGraphError(e.to_string()))?;
let results = oxistore let results = oxistore
.query(parsed, nuri) .query(parsed, nuri)
.map_err(|e| NgError::OxiGraphError(e.to_string()))?; .map_err(|e| NgError::OxiGraphError(e.to_string()))?;
@ -353,7 +379,43 @@ pub fn shape_type_to_sparql_select(
schema: &OrmSchema, schema: &OrmSchema,
shape: &ShapeIri, shape: &ShapeIri,
filter_subjects: Option<Vec<String>>, filter_subjects: Option<Vec<String>>,
limit_to_graph: Option<String>,
) -> Result<String, NgError> { ) -> Result<String, NgError> {
// NOTE FOR MAINTAINERS
// This function generates a SELECT query that mirrors the WHERE semantics of
// `shape_type_to_sparql_construct`, but instead of returning a graph it projects
// triples as rows binding the following variables:
// - ?s: subject
// - ?p: predicate
// - ?o: object
// - ?g: graph name (bound per recursion "layer")
//
// Key ideas:
// - Each shape layer is wrapped in a GRAPH block with its own graph variable (?gN).
// We attribute triples to the layer in which they logically belong by binding ?g
// to that layer’s graph variable when projecting rows.
// - We preserve OPTIONAL, UNION, and the recursive catch-all pattern from the
// CONSTRUCT builder so that validation logic downstream sees the same data surface.
// - We generate two kinds of WHERE content:
// 1) Constraint blocks per layer (GRAPH ?gN { ... }) that ensure the shape matches.
// 2) Projection branches (a UNION of small blocks) that BIND ?s/?p/?o/?g for each
// triple to return. This keeps the constraints readable and separates them from
// the output mapping.
//
// Variable conventions:
// - Term vars: ?v0, ?v1, ... (opaque; used for intermediate subjects/objects)
// - Graph vars: ?g0, ?g1, ... (one per recursion layer, used to bind ?g)
//
// Recursion and cycles:
// - We track visited shapes by IRI to avoid infinite recursion on cyclic schemas.
// - Nested shapes get their own graph var (?gX). We also add a "catch-all" branch
// within that nested layer so that all triples for the nested subject are returned
// for later validation (even if some predicates are optional or missing).
//
// Readability:
// - The generated SPARQL includes comments that "guide through" the query structure
// to make manual inspection and debugging easier.
// Use a counter to generate unique variable names. // Use a counter to generate unique variable names.
let mut var_counter = 0; let mut var_counter = 0;
fn get_new_var_name(counter: &mut i32) -> String { fn get_new_var_name(counter: &mut i32) -> String {
@ -366,6 +428,16 @@ pub fn shape_type_to_sparql_select(
*counter += 1; *counter += 1;
name name
} }
// Small helper to indent multi-line strings by n spaces for cleaner output.
fn indent(s: &str, n: usize) -> String {
let pad = " ".repeat(n);
s.lines()
.map(|l| format!("{}{}", pad, l))
.collect::<Vec<_>>()
.join("\n")
}
// no-op: graph token computed within process_shape where needed
// Collect SELECT branches (each produces bindings for ?s ?p ?o ?g) and shared WHERE constraints. // Collect SELECT branches (each produces bindings for ?s ?p ?o ?g) and shared WHERE constraints.
let mut select_branches: Vec<String> = Vec::new(); let mut select_branches: Vec<String> = Vec::new();
@ -393,7 +465,16 @@ pub fn shape_type_to_sparql_select(
var_counter: &mut i32, var_counter: &mut i32,
visited_shapes: &mut HashSet<String>, visited_shapes: &mut HashSet<String>,
in_recursion: bool, in_recursion: bool,
limit_to_graph: Option<&str>,
) -> Vec<String> { ) -> Vec<String> {
// Helper to render a graph token: either a variable (?gN) or a fixed graph IRI <...>
let graph_token = |graph_var: &str| -> String {
if let Some(g) = limit_to_graph {
format!("<{}>", g)
} else {
format!("?{}", graph_var)
}
};
// Prevent infinite recursion on cyclic schemas. // Prevent infinite recursion on cyclic schemas.
// TODO: We could handle this as IRI string reference. // TODO: We could handle this as IRI string reference.
if visited_shapes.contains(&shape.iri) { if visited_shapes.contains(&shape.iri) {
@ -428,13 +509,14 @@ pub fn shape_type_to_sparql_select(
// Output branch for the parent link triple itself (belongs to current layer) when not in recursive catch-all // Output branch for the parent link triple itself (belongs to current layer) when not in recursive catch-all
if !in_recursion { if !in_recursion {
let branch = format!( let branch = format!(
" GRAPH ?{} {{\n{}\n }}\n BIND(?{} AS ?s)\n BIND(<{}> AS ?p)\n BIND(?{} AS ?o)\n BIND(?{} AS ?g)", " # Output: parent link triple at layer graph {}\n GRAPH {} {{\n{}\n }}\n # Bind row variables\n BIND(?{} AS ?s)\n BIND(<{}> AS ?p)\n BIND(?{} AS ?o)\n BIND({} AS ?g)",
current_graph_var_name, graph_token(current_graph_var_name).as_str(),
graph_token(current_graph_var_name).as_str(),
triple, triple,
subject_var_name, subject_var_name,
predicate.iri, predicate.iri,
obj_var_name, obj_var_name,
current_graph_var_name graph_token(current_graph_var_name).as_str()
); );
select_branches.push(format!("{{\n{}\n}}", branch)); select_branches.push(format!("{{\n{}\n}}", branch));
} }
@ -457,6 +539,7 @@ pub fn shape_type_to_sparql_select(
var_counter, var_counter,
visited_shapes, visited_shapes,
true, true,
limit_to_graph,
); );
nested_where_blocks.extend(nested_blocks); nested_where_blocks.extend(nested_blocks);
} }
@ -473,9 +556,15 @@ pub fn shape_type_to_sparql_select(
if !nested_where_blocks.is_empty() { if !nested_where_blocks.is_empty() {
let nested_joined = nested_where_blocks.join(" .\n"); let nested_joined = nested_where_blocks.join(" .\n");
where_body = format!("{} .\n{}", union_body, nested_joined); where_body = format!(
"# Predicate <{}> with nested shapes in shape <{}>\n{} .\n{}",
predicate.iri, shape.iri, union_body, nested_joined
);
} else { } else {
where_body = union_body; where_body = format!(
"# Predicate <{}> in shape <{}>\n{}",
predicate.iri, shape.iri, union_body
);
} }
} else { } else {
// Value predicate (non-shape) // Value predicate (non-shape)
@ -484,18 +573,22 @@ pub fn shape_type_to_sparql_select(
" ?{} <{}> ?{}", " ?{} <{}> ?{}",
subject_var_name, predicate.iri, obj_var_name subject_var_name, predicate.iri, obj_var_name
); );
where_body = triple.clone(); where_body = format!(
"# Value predicate <{}> in shape <{}>\n{}",
predicate.iri, shape.iri, triple
);
// Output branch for this value triple in current graph layer // Output branch for this value triple in current graph layer
if !in_recursion { if !in_recursion {
let branch = format!( let branch = format!(
" GRAPH ?{} {{\n{}\n }}\n BIND(?{} AS ?s)\n BIND(<{}> AS ?p)\n BIND(?{} AS ?o)\n BIND(?{} AS ?g)", " # Output: value triple at layer graph {}\n GRAPH {} {{\n{}\n }}\n # Bind row variables\n BIND(?{} AS ?s)\n BIND(<{}> AS ?p)\n BIND(?{} AS ?o)\n BIND({} AS ?g)",
current_graph_var_name, graph_token(current_graph_var_name).as_str(),
graph_token(current_graph_var_name).as_str(),
triple, triple,
subject_var_name, subject_var_name,
predicate.iri, predicate.iri,
obj_var_name, obj_var_name,
current_graph_var_name graph_token(current_graph_var_name).as_str()
); );
select_branches.push(format!("{{\n{}\n}}", branch)); select_branches.push(format!("{{\n{}\n}}", branch));
} }
@ -503,7 +596,10 @@ pub fn shape_type_to_sparql_select(
// Optional wrapper, if needed // Optional wrapper, if needed
if predicate.minCardinality < 1 { if predicate.minCardinality < 1 {
new_where_statements.push(format!(" OPTIONAL {{\n{}\n }}", where_body)); new_where_statements.push(format!(
" # OPTIONAL predicate <{}>\n OPTIONAL {{\n{}\n }}",
predicate.iri, where_body
));
} else { } else {
new_where_statements.push(where_body); new_where_statements.push(where_body);
} }
@ -521,33 +617,39 @@ pub fn shape_type_to_sparql_select(
// Output branch for nested triples: include the parent link triple to bind nested subject even when optional // Output branch for nested triples: include the parent link triple to bind nested subject even when optional
if let Some((parent_subj, parent_pred, parent_graph, this_subj)) = link_from_parent { if let Some((parent_subj, parent_pred, parent_graph, this_subj)) = link_from_parent {
let parent_link = format!( let parent_link = format!(
" GRAPH ?{} {{\n ?{} <{}> ?{}\n }}", " # Bind nested subject via parent link (optional-safe)\n GRAPH {} {{\n ?{} <{}> ?{}\n }}",
parent_graph, parent_subj, parent_pred, this_subj graph_token(parent_graph).as_str(),
parent_subj,
parent_pred,
this_subj
); );
let nested_graph_block = format!( let nested_graph_block = format!(
" GRAPH ?{} {{\n{}\n }}", " # Nested layer catch-all in graph {}\n GRAPH {} {{\n{}\n }}",
current_graph_var_name, catch_all graph_token(current_graph_var_name).as_str(),
graph_token(current_graph_var_name).as_str(),
catch_all
); );
let branch = format!( let branch = format!(
"{}\n{}\n BIND(?{} AS ?s)\n BIND(?{} AS ?p)\n BIND(?{} AS ?o)\n BIND(?{} AS ?g)", "{}\n{}\n # Bind row variables\n BIND(?{} AS ?s)\n BIND(?{} AS ?p)\n BIND(?{} AS ?o)\n BIND({} AS ?g)",
parent_link, parent_link,
nested_graph_block, nested_graph_block,
subject_var_name, subject_var_name,
pred_var_name, pred_var_name,
obj_var_name, obj_var_name,
current_graph_var_name graph_token(current_graph_var_name).as_str()
); );
select_branches.push(format!("{{\n{}\n}}", branch)); select_branches.push(format!("{{\n{}\n}}", branch));
} else { } else {
// Fallback: no explicit parent link (shouldn't happen for nested shapes), still output within graph // Fallback: no explicit parent link (shouldn't happen for nested shapes), still output within graph
let branch = format!( let branch = format!(
" GRAPH ?{} {{\n{}\n }}\n BIND(?{} AS ?s)\n BIND(?{} AS ?p)\n BIND(?{} AS ?o)\n BIND(?{} AS ?g)", " # Nested layer catch-all in graph {}\n GRAPH {} {{\n{}\n }}\n # Bind row variables\n BIND(?{} AS ?s)\n BIND(?{} AS ?p)\n BIND(?{} AS ?o)\n BIND({} AS ?g)",
current_graph_var_name, graph_token(current_graph_var_name).as_str(),
graph_token(current_graph_var_name).as_str(),
catch_all, catch_all,
subject_var_name, subject_var_name,
pred_var_name, pred_var_name,
obj_var_name, obj_var_name,
current_graph_var_name graph_token(current_graph_var_name).as_str()
); );
select_branches.push(format!("{{\n{}\n}}", branch)); select_branches.push(format!("{{\n{}\n}}", branch));
} }
@ -555,16 +657,20 @@ pub fn shape_type_to_sparql_select(
// Combine catch-all with specific predicates of this nested shape inside its graph // Combine catch-all with specific predicates of this nested shape inside its graph
let joined_where_statements = new_where_statements.join(" .\n"); let joined_where_statements = new_where_statements.join(" .\n");
let inner_union = if joined_where_statements.is_empty() { let inner_union = if joined_where_statements.is_empty() {
format!("{{{}}}", catch_all) format!("{{\n{}\n }}", catch_all)
} else { } else {
format!( format!(
"{{{}}} UNION {{\n {}\n }}", "{{\n{}\n }} UNION {{\n{}\n }}",
catch_all, joined_where_statements catch_all,
indent(&joined_where_statements, 2)
) )
}; };
let nested_block = format!( let nested_block = format!(
" GRAPH ?{} {{\n {}\n }}", " # Nested shape <{}> constraints in graph {}\n GRAPH {} {{\n {}\n }}",
current_graph_var_name, inner_union shape.iri,
graph_token(current_graph_var_name).as_str(),
graph_token(current_graph_var_name).as_str(),
inner_union
); );
visited_shapes.remove(&shape.iri); visited_shapes.remove(&shape.iri);
return vec![nested_block]; return vec![nested_block];
@ -573,8 +679,11 @@ pub fn shape_type_to_sparql_select(
if !new_where_statements.is_empty() { if !new_where_statements.is_empty() {
let body = new_where_statements.join(" .\n"); let body = new_where_statements.join(" .\n");
where_statements.push(format!( where_statements.push(format!(
" GRAPH ?{} {{\n{}\n }}", " # Shape <{}> constraints in graph {}\n GRAPH {} {{\n{}\n }}",
current_graph_var_name, body shape.iri,
graph_token(current_graph_var_name).as_str(),
graph_token(current_graph_var_name).as_str(),
body
)); ));
} }
} }
@ -600,6 +709,7 @@ pub fn shape_type_to_sparql_select(
&mut var_counter, &mut var_counter,
&mut visited_shapes, &mut visited_shapes,
false, false,
limit_to_graph.as_deref(),
); );
// Filter subjects, if present (applies to the root subject var) // Filter subjects, if present (applies to the root subject var)
@ -609,21 +719,42 @@ pub fn shape_type_to_sparql_select(
.map(|s| format!("<{}>", s)) .map(|s| format!("<{}>", s))
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join(", "); .join(", ");
where_statements.push(format!(" FILTER(?v0 IN ({}))", subjects_str)); where_statements.push(format!(
" # Root subject filter\n FILTER(?v0 IN ({}))",
subjects_str
));
} }
// Assemble final query // Assemble final query body with a guided walkthrough as comments
let mut where_parts: Vec<String> = Vec::new(); let mut where_body = String::new();
if !where_statements.is_empty() { if !where_statements.is_empty() {
where_parts.push(where_statements.join(" .\n")); where_body.push_str(" # 1) Shape constraints per layer (wrapped in GRAPH ?gN)\n");
where_body.push_str(&where_statements.join(" .\n"));
where_body.push_str("\n\n");
} }
if !select_branches.is_empty() { if !select_branches.is_empty() {
let union_body = select_branches.join(" UNION "); where_body.push_str(
where_parts.push(union_body); " # 2) Output projection: one UNION branch per triple (binds ?s ?p ?o ?g)\n",
);
where_body.push_str(&select_branches.join(" UNION "));
where_body.push_str("\n");
} }
// Header comments providing context for the generated query
let header = if let Some(ref g) = limit_to_graph {
format!(
"# NextGraph ORM auto-generated SELECT over shape <{}>\n# Returns (?s ?p ?o) with per-layer graph binding (?g)\n# Limited to graph <{}>\n",
shape, g
)
} else {
format!(
"# NextGraph ORM auto-generated SELECT over shape <{}>\n# Returns (?s ?p ?o) with per-layer graph binding (?g)\n",
shape
)
};
Ok(format!( Ok(format!(
"SELECT DISTINCT ?s ?p ?o ?g\nWHERE {{\n{}\n}}", "{}SELECT DISTINCT ?s ?p ?o ?g\nWHERE {{\n{}\n}}",
where_parts.join(" .\n") header, where_body
)) ))
} }

@ -42,6 +42,7 @@ use ng_net::types::*;
use ng_net::utils::{spawn_and_log_error, Receiver, ResultSend, Sender}; use ng_net::utils::{spawn_and_log_error, Receiver, ResultSend, Sender};
use ng_net::{actor::*, actors::admin::*}; use ng_net::{actor::*, actors::admin::*};
use ng_verifier::orm::types::ShapeIri;
use ng_verifier::types::*; use ng_verifier::types::*;
use ng_verifier::verifier::Verifier; use ng_verifier::verifier::Verifier;
@ -2746,7 +2747,8 @@ pub async fn doc_sparql_update(
} }
} }
async fn get_broker() -> Result<async_std::sync::RwLockWriteGuard<'static, LocalBroker>, NgError> { pub async fn get_broker() -> Result<async_std::sync::RwLockWriteGuard<'static, LocalBroker>, NgError>
{
let broker = match LOCAL_BROKER.get() { let broker = match LOCAL_BROKER.get() {
None | Some(Err(_)) => return Err(NgError::LocalBrokerNotInitialized), None | Some(Err(_)) => return Err(NgError::LocalBrokerNotInitialized),
Some(Ok(broker)) => broker.write().await, Some(Ok(broker)) => broker.write().await,
@ -2786,6 +2788,21 @@ pub async fn doc_sparql_construct(
session.verifier.query_sparql_construct(sparql, nuri) session.verifier.query_sparql_construct(sparql, nuri)
} }
/// Runs the shape-type-based quad query using the verifier helper, returning triples.
pub async fn doc_query_quads_for_shape_type(
session_id: u64,
nuri: Option<String>,
schema: &ng_net::orm::OrmSchema,
shape: &ShapeIri,
filter_subjects: Option<Vec<String>>,
) -> Result<Vec<Triple>, NgError> {
let broker = get_broker().await?;
let session = broker.get_session(session_id)?;
session
.verifier
.query_quads_for_shape_type(nuri, schema, shape, filter_subjects)
}
pub async fn doc_create( pub async fn doc_create(
session_id: u64, session_id: u64,
crdt: String, crdt: String,

@ -7,7 +7,9 @@
// notice may not be copied, modified, or distributed except // notice may not be copied, modified, or distributed except
// according to those terms. // according to those terms.
use crate::local_broker::{doc_create, doc_sparql_construct, doc_sparql_update, orm_start}; use crate::local_broker::{
doc_create, doc_query_quads_for_shape_type, doc_sparql_update, get_broker, orm_start,
};
use crate::tests::create_or_open_wallet::create_or_open_wallet; use crate::tests::create_or_open_wallet::create_or_open_wallet;
use crate::tests::{assert_json_eq, create_doc_with_data}; use crate::tests::{assert_json_eq, create_doc_with_data};
use async_std::stream::StreamExt; use async_std::stream::StreamExt;
@ -18,7 +20,7 @@ use ng_net::orm::{
}; };
use ng_repo::{log_debug, log_info}; use ng_repo::{log_debug, log_info};
use ng_verifier::orm::query::shape_type_to_sparql_select; // use ng_verifier::orm::query::shape_type_to_sparql_select; // replaced by query_quads_for_shape_type
use serde_json::json; use serde_json::json;
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::Arc; use std::sync::Arc;
@ -77,12 +79,16 @@ INSERT DATA {
shape: "http://example.org/TestObject".to_string(), shape: "http://example.org/TestObject".to_string(),
}; };
// Generate and execute the CONSTRUCT query // Query triples using the new helper
let query = shape_type_to_sparql_select(&shape_type.schema, &shape_type.shape, None).unwrap(); let triples = doc_query_quads_for_shape_type(
session_id,
let triples = doc_sparql_construct(session_id, query, Some(doc_nuri.clone())) Some(doc_nuri.clone()),
&shape_type.schema,
&shape_type.shape,
None,
)
.await .await
.expect("SPARQL construct failed"); .expect("shape query failed");
// Assert the results // Assert the results
let predicates: Vec<String> = triples let predicates: Vec<String> = triples
@ -181,8 +187,13 @@ INSERT DATA {
}; };
// Generate and run query // Generate and run query
let query = shape_type_to_sparql_select(&shape_type.schema, &shape_type.shape, None).unwrap(); let triples = doc_query_quads_for_shape_type(
let triples = doc_sparql_construct(session_id, query, Some(doc_nuri.clone())) session_id,
Some(doc_nuri.clone()),
&shape_type.schema,
&shape_type.shape,
None,
)
.await .await
.unwrap(); .unwrap();
@ -244,8 +255,13 @@ INSERT DATA {
}; };
// Generate and run query // Generate and run query
let query = shape_type_to_sparql_select(&shape_type.schema, &shape_type.shape, None).unwrap(); let triples = doc_query_quads_for_shape_type(
let triples = doc_sparql_construct(session_id, query, Some(doc_nuri.clone())) session_id,
Some(doc_nuri.clone()),
&shape_type.schema,
&shape_type.shape,
None,
)
.await .await
.unwrap(); .unwrap();
@ -319,8 +335,13 @@ INSERT DATA {
}; };
// Generate and run query. This must not infinite loop. // Generate and run query. This must not infinite loop.
let query = shape_type_to_sparql_select(&shape_type.schema, &shape_type.shape, None).unwrap(); let triples = doc_query_quads_for_shape_type(
let triples = doc_sparql_construct(session_id, query, Some(doc_nuri.clone())) session_id,
Some(doc_nuri.clone()),
&shape_type.schema,
&shape_type.shape,
None,
)
.await .await
.unwrap(); .unwrap();

Loading…
Cancel
Save