/** * Tests whether an algebra expression gives the same results when run both with and without a * given optimizer * * @param algStr Algebra * @param ds Dataset * @param opt Optimizer * @param expected Expected number of results */ public static void testAsAlgebra(String algStr, Dataset ds, Symbol opt, int expected) { Op op = SSE.parseOp(algStr); List<String> vars = new ArrayList<>(); for (Var v : OpVars.visibleVars(op)) { vars.add(v.getName()); } // Track current state boolean isEnabled = ARQ.isTrue(opt); boolean isDisabled = ARQ.isFalse(opt); try { // Run first without optimization ARQ.set(opt, false); QueryEngineMain engine = new QueryEngineMain(op, ds.asDatasetGraph(), BindingFactory.binding(), ARQ.getContext()); QueryIterator iter = engine.eval(op, ds.asDatasetGraph(), BindingFactory.binding(), ARQ.getContext()); ResultSetRewindable rs = ResultSetFactory.makeRewindable( new ResultSetStream(vars, ModelFactory.createDefaultModel(), iter)); if (expected != rs.size()) { System.err.println("Non-optimized results not as expected"); TextOutput output = new TextOutput((SerializationContext) null); output.format(System.out, rs); rs.reset(); } Assert.assertEquals(expected, rs.size()); iter.close(); // Run with optimization ARQ.set(opt, true); engine = new QueryEngineMain(op, ds.asDatasetGraph(), BindingFactory.binding(), ARQ.getContext()); QueryIterator iterOpt = engine.eval(op, ds.asDatasetGraph(), BindingFactory.binding(), ARQ.getContext()); ResultSetRewindable rsOpt = ResultSetFactory.makeRewindable( new ResultSetStream(vars, ModelFactory.createDefaultModel(), iterOpt)); if (expected != rsOpt.size()) { System.err.println("Optimized results not as expected"); TextOutput output = new TextOutput((SerializationContext) null); output.format(System.out, rsOpt); rsOpt.reset(); } Assert.assertEquals(expected, rsOpt.size()); iterOpt.close(); Assert.assertTrue(ResultSetCompare.isomorphic(rs, rsOpt)); } finally { // Restore previous state if (isEnabled) { ARQ.set(opt, true); } else if (isDisabled) { ARQ.set(opt, false); } else { ARQ.unset(opt); } } }
void runTestSelect(Query query, QueryExecution qe) throws Exception { // Do the query! ResultSetRewindable resultsActual = ResultSetFactory.makeRewindable(qe.execSelect()); qe.close(); if (results == null) return; // Assumes resultSetCompare can cope with full isomorphism possibilities. ResultSetRewindable resultsExpected; if (results.isResultSet()) resultsExpected = ResultSetFactory.makeRewindable(results.getResultSet()); else if (results.isModel()) resultsExpected = ResultSetFactory.makeRewindable(results.getModel()); else { fail("Wrong result type for SELECT query"); resultsExpected = null; // Keep the compiler happy } if (query.isReduced()) { // Reduced - best we can do is DISTINCT resultsExpected = unique(resultsExpected); resultsActual = unique(resultsActual); } // Hack for CSV : tests involving bNodes need manually checking. if (testItem.getResultFile().endsWith(".csv")) { resultsActual = convertToStrings(resultsActual); resultsActual.reset(); int nActual = ResultSetFormatter.consume(resultsActual); int nExpected = ResultSetFormatter.consume(resultsExpected); resultsActual.reset(); resultsExpected.reset(); assertEquals("CSV: Different number of rows", nExpected, nActual); boolean b = resultSetEquivalent(query, resultsExpected, resultsActual); if (!b) System.out.println("Manual check of CSV results required: " + testItem.getName()); return; } boolean b = resultSetEquivalent(query, resultsExpected, resultsActual); if (!b) { resultsExpected.reset(); resultsActual.reset(); boolean b2 = resultSetEquivalent(query, resultsExpected, resultsActual); printFailedResultSetTest(query, qe, resultsExpected, resultsActual); } assertTrue("Results do not match: " + testItem.getName(), b); return; }
/** * Tests whether a query gives the same results when run both with and without a given optimizer * * @param queryStr Query * @param ds Dataset * @param opt Optimizer * @param expected Expected number of results */ public static void test(String queryStr, Dataset ds, Symbol opt, int expected) { Query q = QueryFactory.create(queryStr); if (!q.isSelectType()) Assert.fail("Only SELECT queries are testable with this method"); Op op = Algebra.compile(q); // Track current state boolean isEnabled = ARQ.isTrue(opt); boolean isDisabled = ARQ.isFalse(opt); try { // Run first without optimization ARQ.set(opt, false); ResultSetRewindable rs; try (QueryExecution qe = QueryExecutionFactory.create(q, ds)) { rs = ResultSetFactory.makeRewindable(qe.execSelect()); if (expected != rs.size()) { System.err.println("Non-optimized results not as expected"); TextOutput output = new TextOutput((SerializationContext) null); output.format(System.out, rs); rs.reset(); } Assert.assertEquals(expected, rs.size()); } // Run with optimization ARQ.set(opt, true); ResultSetRewindable rsOpt; try (QueryExecution qeOpt = QueryExecutionFactory.create(q, ds)) { rsOpt = ResultSetFactory.makeRewindable(qeOpt.execSelect()); if (expected != rsOpt.size()) { System.err.println("Optimized results not as expected"); TextOutput output = new TextOutput((SerializationContext) null); output.format(System.out, rsOpt); rsOpt.reset(); } Assert.assertEquals(expected, rsOpt.size()); } Assert.assertTrue(ResultSetCompare.isomorphic(rs, rsOpt)); } finally { // Restore previous state if (isEnabled) { ARQ.set(opt, true); } else if (isDisabled) { ARQ.set(opt, false); } else { ARQ.unset(opt); } } }
private static ResultSetRewindable unique(ResultSetRewindable results) { // VERY crude. Utilises the fact that bindings have value equality. List<Binding> x = new ArrayList<Binding>(); Set<Binding> seen = new HashSet<Binding>(); for (; results.hasNext(); ) { Binding b = results.nextBinding(); if (seen.contains(b)) continue; seen.add(b); x.add(b); } QueryIterator qIter = new QueryIterPlainWrapper(x.iterator()); ResultSet rs = new ResultSetStream(results.getResultVars(), ModelFactory.createDefaultModel(), qIter); return ResultSetFactory.makeRewindable(rs); }
@Test public void testUnionWorks() { Dataset ds = (Dataset) AssemblerUtils.build("union.ttl", SDBConnect.TYPE); ReconnectingDatasetGraph toQuery = (ReconnectingDatasetGraph) ds.asDatasetGraph(); toQuery.getDatasetGraph().getStore().getTableFormatter().format(); UpdateRequest ur = UpdateFactory.create( "insert data {" + "graph <http://example.com/a> { <http://example.com/1> <http://example.com/prop> 1 }" + "graph <http://example.com/b> { <http://example.com/2> <http://example.com/prop> 2 }" + "}"); UpdateProcessor u = UpdateExecutionFactory.create(ur, toQuery); u.execute(); QueryExecution qe = QueryExecutionFactory.create("SELECT * { ?s ?p ?o }", ds); ResultSetRewindable r = ResultSetFactory.makeRewindable(qe.execSelect()); assertEquals("We have a union!", 2, r.size()); }
private ResultSetRewindable convertToStrings(ResultSetRewindable resultsActual) { List<Binding> bindings = new ArrayList<Binding>(); while (resultsActual.hasNext()) { Binding b = resultsActual.nextBinding(); BindingMap b2 = BindingFactory.create(); for (String vn : resultsActual.getResultVars()) { Var v = Var.alloc(vn); Node n = b.get(v); String s; if (n == null) s = ""; else if (n.isBlank()) s = "_:" + n.getBlankNodeLabel(); else s = NodeFunctions.str(n); b2.add(v, NodeFactory.createLiteral(s)); } bindings.add(b2); } ResultSet rs = new ResultSetStream( resultsActual.getResultVars(), null, new QueryIterPlainWrapper(bindings.iterator())); return ResultSetFactory.makeRewindable(rs); }