AlgebraExplorationTest.java
/*******************************************************************************
* Copyright (c) 2025 Eclipse RDF4J contributors.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
******************************************************************************/
package org.eclipse.rdf4j.queryrender;
import org.eclipse.rdf4j.query.MalformedQueryException;
import org.eclipse.rdf4j.query.QueryLanguage;
import org.eclipse.rdf4j.query.algebra.TupleExpr;
import org.eclipse.rdf4j.query.parser.ParsedQuery;
import org.eclipse.rdf4j.query.parser.QueryParserUtil;
import org.eclipse.rdf4j.queryrender.sparql.TupleExprIRRenderer;
import org.junit.jupiter.api.Test;
/**
* Ad-hoc exploration tests to inspect the TupleExpr (algebra) RDF4J produces for various SPARQL constructs. These tests
* intentionally do not assert, they print the algebra and the re-rendered query (with IR debug enabled on failure in
* other tests).
*/
public class AlgebraExplorationTest {
private static final String SPARQL_PREFIX = "BASE <http://ex/>\n" +
"PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>\n" +
"PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>\n" +
"PREFIX foaf: <http://xmlns.com/foaf/0.1/>\n" +
"PREFIX ex: <http://ex/>\n" +
"PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>\n";
private static TupleExpr parseAlgebra(String sparql) {
try {
ParsedQuery pq = QueryParserUtil.parseQuery(QueryLanguage.SPARQL, sparql, null);
return pq.getTupleExpr();
} catch (MalformedQueryException e) {
String msg = "Failed to parse SPARQL query.\n" +
"###### QUERY ######\n" + sparql + "\n\n######################";
throw new MalformedQueryException(msg, e);
}
}
private static TupleExprIRRenderer.Config cfg() {
TupleExprIRRenderer.Config style = new TupleExprIRRenderer.Config();
style.prefixes.put("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
style.prefixes.put("rdfs", "http://www.w3.org/2000/01/rdf-schema#");
style.prefixes.put("foaf", "http://xmlns.com/foaf/0.1/");
style.prefixes.put("ex", "http://ex/");
style.prefixes.put("xsd", "http://www.w3.org/2001/XMLSchema#");
style.valuesPreserveOrder = true;
return style;
}
@Test
void explore_service_graph_nested_1() {
String q = SPARQL_PREFIX +
"SELECT ?s ?o WHERE {\n" +
" {\n" +
" SERVICE SILENT <http://federation.example/ep> {\n" +
" {\n" +
" GRAPH <http://graphs.example/g0> {\n" +
" {\n" +
" GRAPH ?g0 {\n" +
" ?s !(ex:pA|^<http://example.org/p/I1>) ?o . \n" +
" }\n" +
" }\n" +
" }\n" +
" }\n" +
" }\n" +
" }\n" +
"}\n";
TupleExpr te = parseAlgebra(q);
// System.out.println("\n# EXPLORE: SERVICE + nested GRAPH (1)\n\n# SPARQL\n" + q);
// System.out.println("\n# Algebra\n" + te + "\n");
String rendered = new TupleExprIRRenderer(cfg()).render(te, null).trim();
// System.out.println("# Rendered\n" + rendered + "\n");
}
@Test
void explore_service_graph_nested_2() {
String q = SPARQL_PREFIX +
"SELECT ?s ?o WHERE {\n" +
" {\n" +
" SERVICE SILENT <http://federation.example/ep> {\n" +
" {\n" +
" GRAPH ?g1 {\n" +
" {\n" +
" GRAPH <http://graphs.example/g1> {\n" +
" ?s !(ex:pA|^<http://example.org/p/I1>) ?o . \n" +
" }\n" +
" }\n" +
" }\n" +
" }\n" +
" }\n" +
" }\n" +
"}\n";
TupleExpr te = parseAlgebra(q);
// System.out.println("\n# EXPLORE: SERVICE + nested GRAPH (2)\n\n# SPARQL\n" + q);
// System.out.println("\n# Algebra\n" + te + "\n");
String rendered = new TupleExprIRRenderer(cfg()).render(te, null).trim();
// System.out.println("# Rendered\n" + rendered + "\n");
}
@Test
void explore_service_values_minus_fuse_nps_union() {
String q = SPARQL_PREFIX +
"SELECT ?s ?o WHERE {\n" +
" {\n" +
" SERVICE SILENT <http://federation.example/ep> {\n" +
" {\n" +
" VALUES ?s { ex:s1 ex:s2 }\n" +
" { ?s ex:pB ?v0 . MINUS { ?s !(ex:pA|^foaf:knows) ?o . } }\n" +
" }\n" +
" }\n" +
" }\n" +
"}\n";
TupleExpr te = parseAlgebra(q);
// System.out.println("\n# EXPLORE: SERVICE + VALUES + MINUS (NPS union)\n\n# SPARQL\n" + q);
// System.out.println("\n# Algebra\n" + te + "\n");
String rendered = new TupleExprIRRenderer(cfg()).render(te, null).trim();
// System.out.println("# Rendered\n" + rendered + "\n");
}
}