use rete_core::{
auto_block, eval_query, BlockCacheReader, CountingReader, Header, RangeReader, Rete,
SummaryView, HEADER_LEN,
};
use crate::commands::card;
use crate::commands::range_source::RangedSourceReader;
use crate::commands::render::print_query_output;
pub(crate) fn card_url(url: &str, json: bool) -> anyhow::Result<()> {
let reader = CountingReader::new(RangedSourceReader::open(url)?);
let total = reader.len();
match card::load_card_ranged(&reader)? {
None => println!("(no dataset card)"),
Some(dataset_card) => {
if json {
println!(
"{}",
serde_json::to_string_pretty(&card::card_json(&dataset_card))?
);
} else {
let head = reader.read_at(0, HEADER_LEN as u64)?;
let checksum = Header::from_bytes(&head)
.map(|h| card::hex16(&h.content_hash))
.unwrap_or_default();
println!("{}", card::format_card(&dataset_card, &checksum));
}
}
}
eprintln!(
"fetched {} of {} bytes in {} range request(s) — index NOT fetched",
reader.bytes_read(),
total,
reader.requests()
);
Ok(())
}
pub(crate) fn summary_url(url: &str) -> anyhow::Result<()> {
let reader = CountingReader::new(RangedSourceReader::open(url)?);
let total = reader.len();
match SummaryView::open_ranged(&reader)? {
Some(view) => {
println!(
"pyramid round {} — {} communities, {} superedge(s):",
view.round,
view.community_count(),
view.summary.len()
);
for e in &view.summary {
let pred = view
.predicate_term(e.predicate)
.unwrap_or_else(|| format!("#{}", e.predicate));
let arrow = if e.s_comm == e.o_comm {
"(internal)"
} else {
"->"
};
println!(
" C{} {arrow} C{} via {pred} x{}",
e.s_comm, e.o_comm, e.count
);
}
crate::commands::inspect::render_schema_overview(&view);
eprintln!(
"fetched {} of {} bytes in {} range request(s) — index NOT fetched",
reader.bytes_read(),
total,
reader.requests()
);
}
None => eprintln!("file has no pyramid"),
}
Ok(())
}
pub(crate) fn query_url(
url: &str,
s: Option<String>,
p: Option<String>,
o: Option<String>,
) -> anyhow::Result<()> {
let reader = CountingReader::new(RangedSourceReader::open(url)?);
let total = reader.len();
let results = Rete::query_ranged(&reader, s.as_deref(), p.as_deref(), o.as_deref())?;
for (s, p, o) in &results {
println!("{s} {p} {o} .");
}
eprintln!(
"{} result(s) · fetched {} bytes in {} range request(s) (file is {} bytes)",
results.len(),
reader.bytes_read(),
reader.requests(),
total
);
Ok(())
}
pub(crate) fn sparql_url(url: &str, query: &str, json: bool, entail: bool) -> anyhow::Result<()> {
let reader = std::sync::Arc::new(CountingReader::new(RangedSourceReader::open(url)?));
let total = reader.len();
let block: u64 = match std::env::var("RETE_BLOCK_KB")
.ok()
.and_then(|v| v.parse::<u64>().ok())
{
Some(kb) => kb * 1024,
None => auto_block(total),
};
let mut rete = if block == 0 {
Rete::open_ranged_lazy(reader.clone())?
} else {
Rete::open_ranged_lazy(std::sync::Arc::new(BlockCacheReader::new(
reader.clone(),
block,
)))?
};
rete.set_service_client(Box::new(super::service_http::HttpServiceClient));
let eval = if entail {
rete_core::eval_query_reasoned
} else {
eval_query
};
let result = eval(&rete, query).map_err(|e| anyhow::anyhow!("{e}"))?;
if rete.index_incomplete() {
anyhow::bail!(
"a range request failed while streaming index tiles from {url}; \
results would be incomplete — retry"
);
}
print_query_output(&result, json);
eprintln!(
"(fetched {} bytes in {} range request(s); file is {} bytes)",
reader.bytes_read(),
reader.requests(),
total
);
Ok(())
}
pub(crate) fn why_url(
url: &str,
subject: Option<String>,
predicate: Option<String>,
object: Option<String>,
json: bool,
) -> anyhow::Result<()> {
let reader = std::sync::Arc::new(CountingReader::new(RangedSourceReader::open(url)?));
let total = reader.len();
let block: u64 = match std::env::var("RETE_BLOCK_KB")
.ok()
.and_then(|v| v.parse::<u64>().ok())
{
Some(kb) => kb * 1024,
None => auto_block(total),
};
let rete = if block == 0 {
Rete::open_ranged_lazy(reader.clone())?
} else {
Rete::open_ranged_lazy(std::sync::Arc::new(BlockCacheReader::new(
reader.clone(),
block,
)))?
};
let results =
rete.query_with_provenance(subject.as_deref(), predicate.as_deref(), object.as_deref());
if rete.index_incomplete() {
anyhow::bail!(
"a range request failed while explaining the pattern over {url}; the \
provenance would be incomplete — retry"
);
}
crate::commands::query::print_provenance(
subject.as_deref(),
predicate.as_deref(),
object.as_deref(),
&results,
json,
)?;
eprintln!(
"(fetched {} bytes in {} range request(s); file is {} bytes)",
reader.bytes_read(),
reader.requests(),
total
);
Ok(())
}