moonsparql

    Bounded in-process SPARQL query evaluation over RDF graphs in MoonBit

    sparql
    rdf
    query
    knowledge-graph
    Download zip
    Author
    Version
    0.3.0
    License
    Apache-2.0
    Last updated
    9 hours ago
    Downloads
    40

    #MoonSparql

    MoonSparql is a bounded, in-process RDF query engine written in MoonBit. It extends existing RDF IO libraries with query execution: joins, optional facts, aggregates and paths return bindings or a derived graph.

    The compatibility target is the complete W3C SPARQL 1.1 Query Language. See delivery scope and remaining gaps.

    Install yyyt0807/moonsparql@0.3.0 from Mooncakes. The source is maintained at yyyt0807/MoonSparql. Repository owner and maintenance commit identity: yyyt0807.

    moon add yyyt0807/moonsparql@0.3.0

    #Run

    Build from source with the MoonBit compiler/core pair 0.10.20+65efd5b93 and a C compiler for the Native CLI. On Windows, install MSVC Build Tools. See MoonTTL linker compatibility.

    moon update moon check --target all --deny-warn moon build --target all --deny-warn moon test --target all --deny-warn moon run examples/asset_inventory --target native moon run examples/catalog_discovery --target native moon run examples/research_summary --target native moon run examples/scale --target native --release moon run cmd/main --target native -- examples/data/catalog.ttl examples/data/catalog.rq json

    CI pins the official compiler/core pair 0.10.20+65efd5b93 on Ubuntu and Windows. For independent common-profile verification after building the Native CLI:

    python -m venv .venv # Activate the environment; on Windows use .venv/Scripts/python.exe. python -m pip install -r scripts/requirements-interop.txt python scripts/compare_rdflib.py _build/native/debug/build/cmd/main/main.exe

    The 15 RDFLib comparisons cover shared semantics only; they do not certify the full SPARQL standard. Python is a development oracle, not a runtime requirement. scripts/verify_repository.py checks real source/history and excludes private contest material from tracked paths and package ZIPs.

    #Library use

    Import the module in the consuming package's moon.pkg:

    import { "yyyt0807/moonsparql" @q, }

    let data = @q.Dataset::from_turtle(
    "<urn:item> <urn:owner> \"Alice\" .",
    )
    let query = @q.prepare("SELECT ?owner {<urn:item> <urn:owner> ?owner}")
    let result = query.execute(data)
    assert_eq(result.rows()[0].get("owner").unwrap().lexical(), "Alice")
    println(result.to_json())

    Programmatic datasets use iri, blank, literal, typed_literal, language_literal, quad and Dataset::from_quads. Named graphs are available through that API. Datasets copy input collections and return copies; bindings expose lookup and variable names without mutable internal maps.

    #Three complete applications

    • Asset impact: join ownership facts with transitive dependencies, retaining assets whose optional owner is missing. This supports inventories, software catalogs, equipment maintenance and change planning.
    • Metadata discovery: combine catalog topic and publisher facts with VALUES restrictions. This supports datasets, documents, product catalogs and institutional metadata.
    • Research summaries: group observations by site, calculate exact SUM/AVG, filter groups and construct a derived RDF view. This supports research, public data and reusable analytical metadata.

    Each example contains assertions for its outputs. The 10,000-fact scale example verifies indexed lookup work and an exact aggregate, without claiming a timing advantage over another engine.

    #Query features in 0.3.0

    • DESCRIBE exports a resource description as RDF quads or N-Triples.
    • MD5, SHA1, SHA256, SHA384 and SHA512 generate UTF-8 content fingerprints within queries.
    • SELECT REDUCED suppresses adjacent equal projected bindings before slicing.

    moon run examples/query_standard --target wasm-gc --deny-warn

    #Query compatibility baseline in 0.2.0

    MoonSparql supports SELECT subqueries, EXISTS and NOT EXISTS, negated property sets, GROUP_CONCAT, GROUP BY aliases, trailing VALUES, and local FROM and FROM NAMED datasets. Extended string and date-time builtins and selected datatype casts are documented with their limits in the query profile.

    The pinned W3C suite runs 236 query evaluations. The release checks show 219 passes and 17 documented unsupported-function cases. Coverage and reproduction commands appear in the query profile.

    Three interfaces support integration in this release.

    • Dataset::from_documents assembles independent RDF sources with named and empty graph support. The Native CLI accepts the same catalogue with --dataset DATA.json QUERY.rq json|tsv|rdf.
    • PreparedQuery::profile and CLI --inspect QUERY.rq expose static projection, data-source IRIs and subquery, existence, path and aggregate counts for validation tools and local catalogues.
    • CONSTRUCT WHERE exports the matched RDF subgraph for catalogue snapshots, metadata exchange and downstream graph processing.

    moon run examples/compatibility --target native --deny-warn moon run cmd/main --target native -- --inspect examples/data/catalog.rq python scripts/check_w3c.py _build/native/debug/build/cmd/main/main.exe --fetch

    The example joins a release catalogue with an advisory graph, aggregates the eligible versions and exports a version subgraph.

    #Ecosystem integration and sources

    MoonTTL provides RDF parsing and materialization. MoonSHACL validates RDF contracts and JSON-LD supplies linked-data interchange. MoonSparql adds query execution over RDF datasets; it does not replace those packages. The dated topic-search evidence and contest materials are stored outside public Git.

    Apache-2.0. Dependency sources, AI assistance and original fixture provenance are recorded in THIRD_PARTY_NOTICES.md. Architecture and costs: docs/architecture.md.

    #十一月新增功能

    精确前置条件的原子数据补丁(Dataset::apply_patch);SELECT结果多重集变化分析(QueryResult::binding_delta)。详见功能、用途和边界,运行 moon run examples/november --target native --deny-warn。这些功能纳入 0.1.0 首次公开发布。

    #RDF 数据集与结果合并

    新增 独立空白节点作用域的 RDF 合并、按列对齐的 SELECT 袋并集,用途、限制和复杂度见 功能文档。 从本仓库源码运行 moon run examples/expansion --target native --deny-warn。 这两项 API 自 0.2.0 起可用。

    QueryError

    pub(all) suberror QueryError {
    InvalidTerm(String)
    Syntax(Int, String)
    Unsupported(Int, String)
    Resource(String)
    Evaluation(String)
    InvalidInput(String)
    } derive(
    Debug
    )

    QueryError::message

    fn QueryError::message(self : QueryError) -> String

    Binding

    pub struct Binding {
    // private fields
    }

    Binding::get

    fn Binding::get(self : Binding, variable : String) -> Term?

    Binding::length

    fn Binding::length(self : Binding) -> Int

    Binding::variables

    fn Binding::variables(self : Binding) -> Array[String]

    BindingDelta

    pub(all) struct BindingDelta {
    added : Array[Binding]
    removed : Array[Binding]
    retained : Int
    }

    Dataset

    pub struct Dataset {
    // private fields
    }

    Dataset::apply_patch

    fn Dataset::apply_patch(self : Dataset, remove : Array[Quad], add : Array[Quad], limits? : Limits) -> Dataset raise QueryError

    Host-side exact patch, not SPARQL UPDATE. All preconditions are checked on the original snapshot; failure leaves the dataset and its indexes unchanged.

    Dataset::from_documents

    fn Dataset::from_documents(default_graph : String, named_graphs : Array[(Term, String)], limits? : Limits) -> Dataset raise QueryError

    Assemble a default Turtle document and explicitly named local documents. Blank-node labels are scoped to each document, including empty named graphs.

    Dataset::from_quads

    fn Dataset::from_quads(quads : Array[Quad], named_graphs? : Array[Term], limits? : Limits) -> Dataset raise QueryError

    Dataset::from_turtle

    fn Dataset::from_turtle(source : String, limits? : Limits) -> Dataset raise QueryError

    Dataset::graph_names

    fn Dataset::graph_names(self : Dataset) -> Array[Term]

    Dataset::length

    fn Dataset::length(self : Dataset) -> Int

    Dataset::matching

    fn Dataset::matching(self : Dataset, subject? : Term, predicate? : Term, object? : Term, graph? : Term, limits? : Limits) -> Array[Quad] raise QueryError

    Dataset::merge_scoped

    fn Dataset::merge_scoped(self : Dataset, other : Dataset, limits? : Limits) -> Dataset raise QueryError

    RDF merge of independently scoped documents: all right-hand blank nodes are consistently renamed, ground quads deduplicate, named IRI graphs are retained.

    Dataset::quads

    fn Dataset::quads(self : Dataset) -> Array[Quad]

    ExecutionStats

    pub(all) struct ExecutionStats {
    steps : Int
    peak_bindings : Int
    path_pairs : Int
    } derive(Eq,
    Debug
    )

    ExecutionStats::equal

    ExecutionStats::not_equal

    fn ExecutionStats::not_equal(x : ExecutionStats, y : ExecutionStats) -> Bool

    Limits

    pub(all) struct Limits {
    max_triples : Int
    max_query_chars : Int
    max_tokens : Int
    max_depth : Int
    max_steps : Int
    max_bindings : Int
    max_results : Int
    max_path_pairs : Int
    max_numeric_digits : Int
    } derive(Eq,
    Debug
    )

    Limits::default

    fn Limits::default() -> Limits

    Limits::equal

    fn Limits::equal(Limits, Limits) -> Bool

    Limits::not_equal

    fn Limits::not_equal(x : Limits, y : Limits) -> Bool

    Limits::to_repr

    PreparedQuery

    pub struct PreparedQuery {
    // private fields
    }

    PreparedQuery::dataset_sources

    fn PreparedQuery::dataset_sources(self : PreparedQuery) -> Array[(Term, Bool)]

    Pairs contain an IRI and whether its clause is FROM NAMED.

    PreparedQuery::execute

    fn PreparedQuery::execute(self : PreparedQuery, data : Dataset) -> QueryResult raise QueryError

    PreparedQuery::form

    fn PreparedQuery::form(self : PreparedQuery) -> String

    PreparedQuery::profile

    Quad

    pub struct Quad {
    // private fields
    } derive(Eq,
    Debug
    )

    Quad::equal

    fn Quad::equal(Quad, Quad) -> Bool

    Quad::graph

    fn Quad::graph(self : Quad) -> Term?

    Quad::not_equal

    fn Quad::not_equal(x : Quad, y : Quad) -> Bool

    Quad::object

    fn Quad::object(self : Quad) -> Term

    Quad::predicate

    fn Quad::predicate(self : Quad) -> Term

    Quad::subject

    fn Quad::subject(self : Quad) -> Term

    Quad::to_repr

    QueryProfile

    pub struct QueryProfile {
    // private fields
    }

    Static query structure for editors, local source catalogues and capability checks. Counts describe syntax, independently of data and result cardinality.

    QueryProfile::to_json

    fn QueryProfile::to_json(self : QueryProfile) -> String

    QueryResult

    pub struct QueryResult {
    // private fields
    }

    QueryResult::answer

    fn QueryResult::answer(self : QueryResult) -> Bool?

    QueryResult::binding_delta

    fn QueryResult::binding_delta(self : QueryResult, newer : QueryResult, limits? : Limits) -> BindingDelta raise QueryError

    Bag-sensitive SELECT comparison: term identity, unbound values and duplicate occurrence counts matter; ordering does not. Blank node IDs must share scope.

    QueryResult::graph

    fn QueryResult::graph(self : QueryResult) -> Array[Quad]

    QueryResult::rows

    fn QueryResult::rows(self : QueryResult) -> Array[Binding]

    QueryResult::statistics

    fn QueryResult::statistics(self : QueryResult) -> ExecutionStats

    QueryResult::to_json

    fn QueryResult::to_json(self : QueryResult) -> String

    QueryResult::to_ntriples

    fn QueryResult::to_ntriples(self : QueryResult) -> String

    QueryResult::to_tsv

    fn QueryResult::to_tsv(self : QueryResult) -> String

    QueryResult::union_bindings

    fn QueryResult::union_bindings(self : QueryResult, other : QueryResult, shared_blank_scope? : Bool, limits? : Limits) -> QueryResult raise QueryError

    Align SELECT columns and append bags in source order, preserving duplicates and unbound values. Independent right-side blank scope is the default. Set shared_blank_scope only when both results originate from one RDF scope.

    QueryResult::variables

    fn QueryResult::variables(self : QueryResult) -> Array[String]

    Term

    pub struct Term {
    // private fields
    } derive(Eq,
    Debug
    )

    Term::datatype

    fn Term::datatype(self : Term) -> String?

    Term::equal

    fn Term::equal(Term, Term) -> Bool

    Term::kind

    fn Term::kind(self : Term) -> TermKind

    Term::language

    fn Term::language(self : Term) -> String?

    Term::lexical

    fn Term::lexical(self : Term) -> String

    Term::not_equal

    fn Term::not_equal(x : Term, y : Term) -> Bool

    Term::ntriples

    fn Term::ntriples(self : Term) -> String

    Term::to_repr

    TermKind

    pub(all) enum TermKind {
    IriKind
    BlankKind
    LiteralKind
    } derive(Eq,
    Debug
    )

    TermKind::equal

    fn TermKind::equal(TermKind, TermKind) -> Bool

    TermKind::not_equal

    fn TermKind::not_equal(x : TermKind, y : TermKind) -> Bool

    TermKind::to_repr

    blank

    fn blank(value : String) -> Term raise QueryError

    iri

    fn iri(value : String) -> Term raise QueryError

    language_literal

    fn language_literal(value : String, language : String) -> Term raise QueryError

    literal

    fn literal(value : String) -> Term

    prepare

    fn prepare(source : String, limits? : Limits, base_uri? : String) -> PreparedQuery raise QueryError

    quad

    fn quad(subject : Term, predicate : Term, object : Term, graph? : Term) -> Quad raise QueryError

    rdf_namespace

    fn rdf_namespace() -> String

    typed_literal

    fn typed_literal(value : String, datatype : String) -> Term raise QueryError

    validate_result_json

    fn validate_result_json(source : String) -> Bool

    xsd_namespace

    fn xsd_namespace() -> String