/** Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved. Contact: SYSTAP, LLC DBA Blazegraph 2501 Calvert ST NW #106 Washington, DC 20008 licenses@blazegraph.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * Created on Aug 20, 2011 */ package com.bigdata.rdf.sail.sparql; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import org.openrdf.query.MalformedQueryException; import org.openrdf.query.algebra.StatementPattern.Scope; import com.bigdata.bop.Constant; import com.bigdata.bop.IBindingSet; import com.bigdata.bop.IVariable; import com.bigdata.bop.Var; import com.bigdata.bop.bindingSet.ListBindingSet; import com.bigdata.rdf.internal.IV; import com.bigdata.rdf.sail.sparql.ast.ParseException; import com.bigdata.rdf.sail.sparql.ast.TokenMgrError; import com.bigdata.rdf.sail.sparql.ast.VisitorException; import com.bigdata.rdf.sparql.AbstractBigdataExprBuilderTestCase; import com.bigdata.rdf.sparql.ast.BindingsClause; import com.bigdata.rdf.sparql.ast.ConstantNode; import com.bigdata.rdf.sparql.ast.JoinGroupNode; import com.bigdata.rdf.sparql.ast.ProjectionNode; import com.bigdata.rdf.sparql.ast.QueryRoot; import com.bigdata.rdf.sparql.ast.QueryType; import com.bigdata.rdf.sparql.ast.StatementPatternNode; import com.bigdata.rdf.sparql.ast.VarNode; import com.bigdata.util.InnerCause; /** * Test suite for the BINDINGS clause. * * @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a> * @version $Id: TestBigdataExprBuilder.java 5073 2011-08-23 00:33:54Z * thompsonbry $ */ public class TestBindingsClause extends AbstractBigdataExprBuilderTestCase { private static final Logger log = Logger .getLogger(TestBindingsClause.class); public TestBindingsClause() { } public TestBindingsClause(String name) { super(name); } /** * Unit test for the SPARQL 1.1 BINDINGS clause with one binding set having * one binding. * * <pre> * PREFIX : <http://example.org/book/> * SELECT ?title ?price * { * ?book :title ?title ; * :price ?price . * } * BINDINGS ?book { * (:book1) * } * </pre> */ @SuppressWarnings("rawtypes") public void test_bindings_001() throws MalformedQueryException, TokenMgrError, ParseException { final String sparql = "" + // "PREFIX : <http://example.org/book/>\n"+// "SELECT ?title ?price\n" + // "{\n" + // " ?book :title ?title ; \n" + // " :price ?price . \n" + // "}\n" + // "BINDINGS ?book {\n" + // " (:book1)\n" + // "}"// ; final IV<?,?> title = makeIV(valueFactory.createURI("http://example.org/book/title")); final IV<?,?> price = makeIV(valueFactory.createURI("http://example.org/book/price")); final IV<?,?> book1 = makeIV(valueFactory.createURI("http://example.org/book/book1")); final QueryRoot expected = new QueryRoot(QueryType.SELECT); { { final Map<String, String> prefixDecls = new LinkedHashMap<String, String>(PrefixDeclProcessor.defaultDecls); prefixDecls.put("", "http://example.org/book/"); expected.setPrefixDecls(prefixDecls); } final ProjectionNode projection = new ProjectionNode(); projection.addProjectionVar(new VarNode("title")); projection.addProjectionVar(new VarNode("price")); expected.setProjection(projection); final JoinGroupNode whereClause = new JoinGroupNode(); expected.setWhereClause(whereClause); whereClause.addChild(new StatementPatternNode(new VarNode("book"), new ConstantNode(new Constant<IV>(title)), new VarNode("title"), null/* c */, Scope.DEFAULT_CONTEXTS)); whereClause.addChild(new StatementPatternNode(new VarNode("book"), new ConstantNode(new Constant<IV>(price)), new VarNode("price"), null/* c */, Scope.DEFAULT_CONTEXTS)); final LinkedHashSet<IVariable<?>> declaredVars = new LinkedHashSet<IVariable<?>>(); declaredVars.add(Var.var("book")); final List<IBindingSet> bindings = new LinkedList<IBindingSet>(); { final IBindingSet bset = new ListBindingSet(); bset.set(Var.var("book"), new Constant<IV>(book1)); bindings.add(bset); } final BindingsClause bindingsClause = new BindingsClause( declaredVars, bindings); expected.setBindingsClause(bindingsClause); } final QueryRoot actual = parse(sparql, baseURI); assertSameAST(sparql, expected, actual); } /** * Unit test for the SPARQL 1.1 BINDINGS clause with an UNDEF binding. * * <pre> * PREFIX : <http://example.org/book/> * SELECT ?title ?price * { * ?book :title ?title ; * :price ?price . * } * BINDINGS ?book { * (UNDEF) * } * </pre> */ @SuppressWarnings("rawtypes") public void test_bindings_002() throws MalformedQueryException, TokenMgrError, ParseException { final String sparql = "" + // "PREFIX : <http://example.org/book/>\n"+// "SELECT ?title ?price\n" + // "{\n" + // " ?book :title ?title ; \n" + // " :price ?price . \n" + // "}\n" + // "BINDINGS ?book {\n" + // " (UNDEF)\n" + // "}"// ; final IV<?,?> title = makeIV(valueFactory.createURI("http://example.org/book/title")); final IV<?,?> price = makeIV(valueFactory.createURI("http://example.org/book/price")); // final IV<?,?> book1 = makeIV(valueFactory.createURI("http://example.org/book/book1")); final QueryRoot expected = new QueryRoot(QueryType.SELECT); { { final Map<String, String> prefixDecls = new LinkedHashMap<String, String>(PrefixDeclProcessor.defaultDecls); prefixDecls.put("", "http://example.org/book/"); expected.setPrefixDecls(prefixDecls); } final ProjectionNode projection = new ProjectionNode(); projection.addProjectionVar(new VarNode("title")); projection.addProjectionVar(new VarNode("price")); expected.setProjection(projection); final JoinGroupNode whereClause = new JoinGroupNode(); expected.setWhereClause(whereClause); whereClause.addChild(new StatementPatternNode(new VarNode("book"), new ConstantNode(new Constant<IV>(title)), new VarNode("title"), null/* c */, Scope.DEFAULT_CONTEXTS)); whereClause.addChild(new StatementPatternNode(new VarNode("book"), new ConstantNode(new Constant<IV>(price)), new VarNode("price"), null/* c */, Scope.DEFAULT_CONTEXTS)); final LinkedHashSet<IVariable<?>> declaredVars = new LinkedHashSet<IVariable<?>>(); declaredVars.add(Var.var("book")); final List<IBindingSet> bindings = new LinkedList<IBindingSet>(); { final IBindingSet bset = new ListBindingSet(); // bset.set(Var.var("book"), new Constant<IV>(book1)); bindings.add(bset); } final BindingsClause bindingsClause = new BindingsClause( declaredVars, bindings); expected.setBindingsClause(bindingsClause); } final QueryRoot actual = parse(sparql, baseURI); assertSameAST(sparql, expected, actual); } /** * Unit test for the SPARQL 1.1 BINDINGS clause with two binding sets, one * of which has no bound values. * * <pre> * PREFIX : <http://example.org/book/> * SELECT ?title ?price * { * ?book :title ?title ; * :price ?price . * } * BINDINGS ?book { * (:book1) * (UNDEF) * } * </pre> */ @SuppressWarnings("rawtypes") public void test_bindings_003() throws MalformedQueryException, TokenMgrError, ParseException { final String sparql = "" + // "PREFIX : <http://example.org/book/>\n"+// "SELECT ?title ?price\n" + // "{\n" + // " ?book :title ?title ; \n" + // " :price ?price . \n" + // "}\n" + // "BINDINGS ?book {\n" + // " (:book1)\n" + // " (UNDEF)\n" + // "}"// ; final IV<?,?> title = makeIV(valueFactory.createURI("http://example.org/book/title")); final IV<?,?> price = makeIV(valueFactory.createURI("http://example.org/book/price")); final IV<?,?> book1 = makeIV(valueFactory.createURI("http://example.org/book/book1")); final QueryRoot expected = new QueryRoot(QueryType.SELECT); { { final Map<String, String> prefixDecls = new LinkedHashMap<String, String>(PrefixDeclProcessor.defaultDecls); prefixDecls.put("", "http://example.org/book/"); expected.setPrefixDecls(prefixDecls); } final ProjectionNode projection = new ProjectionNode(); projection.addProjectionVar(new VarNode("title")); projection.addProjectionVar(new VarNode("price")); expected.setProjection(projection); final JoinGroupNode whereClause = new JoinGroupNode(); expected.setWhereClause(whereClause); whereClause.addChild(new StatementPatternNode(new VarNode("book"), new ConstantNode(new Constant<IV>(title)), new VarNode("title"), null/* c */, Scope.DEFAULT_CONTEXTS)); whereClause.addChild(new StatementPatternNode(new VarNode("book"), new ConstantNode(new Constant<IV>(price)), new VarNode("price"), null/* c */, Scope.DEFAULT_CONTEXTS)); final LinkedHashSet<IVariable<?>> declaredVars = new LinkedHashSet<IVariable<?>>(); declaredVars.add(Var.var("book")); final List<IBindingSet> bindings = new LinkedList<IBindingSet>(); { final IBindingSet bset = new ListBindingSet(); bset.set(Var.var("book"), new Constant<IV>(book1)); bindings.add(bset); } { final IBindingSet bset = new ListBindingSet(); bindings.add(bset); } final BindingsClause bindingsClause = new BindingsClause( declaredVars, bindings); expected.setBindingsClause(bindingsClause); } final QueryRoot actual = parse(sparql, baseURI); assertSameAST(sparql, expected, actual); } /** * Unit test for the SPARQL 1.1 BINDINGS clause with two binding sets, one * of which does not bind all variables. * * <pre> * PREFIX : <http://example.org/book/> * SELECT ?title ?price * { * ?book :title ?title ; * :price ?price . * } * BINDINGS ?book ?title { * (:book1 :title1) * (:book2 UNDEF) * } * </pre> */ @SuppressWarnings("rawtypes") public void test_bindings_004() throws MalformedQueryException, TokenMgrError, ParseException { final String sparql = "" + // "PREFIX : <http://example.org/book/>\n"+// "SELECT ?title ?price\n" + // "{\n" + // " ?book :title ?title ; \n" + // " :price ?price . \n" + // "}\n" + // "BINDINGS ?book ?title {\n" + // " (:book1 :title1)\n" + // " (:book2 UNDEF)\n" + // "}"// ; final IV<?,?> title = makeIV(valueFactory.createURI("http://example.org/book/title")); final IV<?,?> price = makeIV(valueFactory.createURI("http://example.org/book/price")); final IV<?,?> book1 = makeIV(valueFactory.createURI("http://example.org/book/book1")); final IV<?,?> book2 = makeIV(valueFactory.createURI("http://example.org/book/book2")); final IV<?,?> title1 = makeIV(valueFactory.createURI("http://example.org/book/title1")); final QueryRoot expected = new QueryRoot(QueryType.SELECT); { { final Map<String, String> prefixDecls = new LinkedHashMap<String, String>(PrefixDeclProcessor.defaultDecls); prefixDecls.put("", "http://example.org/book/"); expected.setPrefixDecls(prefixDecls); } final ProjectionNode projection = new ProjectionNode(); projection.addProjectionVar(new VarNode("title")); projection.addProjectionVar(new VarNode("price")); expected.setProjection(projection); final JoinGroupNode whereClause = new JoinGroupNode(); expected.setWhereClause(whereClause); whereClause.addChild(new StatementPatternNode(new VarNode("book"), new ConstantNode(new Constant<IV>(title)), new VarNode("title"), null/* c */, Scope.DEFAULT_CONTEXTS)); whereClause.addChild(new StatementPatternNode(new VarNode("book"), new ConstantNode(new Constant<IV>(price)), new VarNode("price"), null/* c */, Scope.DEFAULT_CONTEXTS)); final LinkedHashSet<IVariable<?>> declaredVars = new LinkedHashSet<IVariable<?>>(); declaredVars.add(Var.var("book")); declaredVars.add(Var.var("title")); final List<IBindingSet> bindings = new LinkedList<IBindingSet>(); { final IBindingSet bset = new ListBindingSet(); bset.set(Var.var("book"), new Constant<IV>(book1)); bset.set(Var.var("title"), new Constant<IV>(title1)); bindings.add(bset); } { final IBindingSet bset = new ListBindingSet(); bset.set(Var.var("book"), new Constant<IV>(book2)); // bset.set(Var.var("title"), new Constant<IV>(title1)); bindings.add(bset); } final BindingsClause bindingsClause = new BindingsClause( declaredVars, bindings); expected.setBindingsClause(bindingsClause); } final QueryRoot actual = parse(sparql, baseURI); assertSameAST(sparql, expected, actual); } /** * Unit test for the SPARQL 1.1 BINDINGS clause with NO variables and NO * binding sets (the spec allows this). * * <pre> * PREFIX : <http://example.org/book/> * SELECT ?title ?price * { * ?book :title ?title ; * :price ?price . * } * BINDINGS { * } * </pre> */ @SuppressWarnings("rawtypes") public void test_bindings_005() throws MalformedQueryException, TokenMgrError, ParseException { final String sparql = "" + // "PREFIX : <http://example.org/book/>\n"+// "SELECT ?title ?price\n" + // "{\n" + // " ?book :title ?title ; \n" + // " :price ?price . \n" + // "}\n" + // "BINDINGS {\n" + // "}"// ; final IV<?,?> title = makeIV(valueFactory.createURI("http://example.org/book/title")); final IV<?,?> price = makeIV(valueFactory.createURI("http://example.org/book/price")); final QueryRoot expected = new QueryRoot(QueryType.SELECT); { { final Map<String, String> prefixDecls = new LinkedHashMap<String, String>(PrefixDeclProcessor.defaultDecls); prefixDecls.put("", "http://example.org/book/"); expected.setPrefixDecls(prefixDecls); } final ProjectionNode projection = new ProjectionNode(); projection.addProjectionVar(new VarNode("title")); projection.addProjectionVar(new VarNode("price")); expected.setProjection(projection); final JoinGroupNode whereClause = new JoinGroupNode(); expected.setWhereClause(whereClause); whereClause.addChild(new StatementPatternNode(new VarNode("book"), new ConstantNode(new Constant<IV>(title)), new VarNode("title"), null/* c */, Scope.DEFAULT_CONTEXTS)); whereClause.addChild(new StatementPatternNode(new VarNode("book"), new ConstantNode(new Constant<IV>(price)), new VarNode("price"), null/* c */, Scope.DEFAULT_CONTEXTS)); /* * Note: The BINDINGS clause is omitted from the AST by the visitor * when there are no binding sets. */ // final LinkedHashSet<IVariable<?>> declaredVars = new LinkedHashSet<IVariable<?>>(); // // final List<IBindingSet> bindings = new LinkedList<IBindingSet>(); // // final BindingsClause bindingsClause = new BindingsClause( // declaredVars, bindings); // // expected.setBindingsClause(bindingsClause); } final QueryRoot actual = parse(sparql, baseURI); assertSameAST(sparql, expected, actual); } /** * Correct rejection test for the SPARQL 1.1 BINDINGS clause with no * variables and a non-empty binding set. * * <pre> * PREFIX : <http://example.org/book/> * SELECT ?title ?price * { * ?book :title ?title ; * :price ?price . * } * BINDINGS { * (:book1) * } * </pre> */ public void test_bindings_006() throws MalformedQueryException, TokenMgrError, ParseException { final String sparql = "" + // "PREFIX : <http://example.org/book/>\n"+// "SELECT ?title ?price\n" + // "{\n" + // " ?book :title ?title ; \n" + // " :price ?price . \n" + // "}\n" + // "BINDINGS {\n" + // " (:book1)\n" + // "}"// ; try { parse(sparql, baseURI); fail("Expecting: " + VisitorException.class); } catch (Throwable t) { if (InnerCause.isInnerCause(t, VisitorException.class)) { if (log.isInfoEnabled()) log.info("Ignoring expected exception: " + t, t); return; } fail("Expecting: " + VisitorException.class); } } /** * Correct rejection test for the SPARQL 1.1 BINDINGS clause with duplicate * variables and a non-empty set of binding sets. * * <pre> * PREFIX : <http://example.org/book/> * SELECT ?title ?price * { * ?book :title ?title ; * :price ?price . * } * BINDINGS ?book ?book { * (:book1 :book2) * } * </pre> */ public void test_bindings_007() throws MalformedQueryException, TokenMgrError, ParseException { final String sparql = "" + // "PREFIX : <http://example.org/book/>\n"+// "SELECT ?title ?price\n" + // "{\n" + // " ?book :title ?title ; \n" + // " :price ?price . \n" + // "}\n" + // "BINDINGS ?book ?book {\n" + // " (:book1 :book2)\n" + // "}"// ; try { parse(sparql, baseURI); fail("Expecting: " + VisitorException.class); } catch (Throwable t) { if (InnerCause.isInnerCause(t, VisitorException.class)) { if (log.isInfoEnabled()) log.info("Ignoring expected exception: " + t, t); return; } fail("Expecting: " + VisitorException.class); } } /** * Correct rejection test for the SPARQL 1.1 BINDINGS clause with duplicate * variables and an empty set of binding sets. * * <pre> * PREFIX : <http://example.org/book/> * SELECT ?title ?price * { * ?book :title ?title ; * :price ?price . * } * BINDINGS ?book ?book { * } * </pre> */ public void test_bindings_008() throws MalformedQueryException, TokenMgrError, ParseException { final String sparql = "" + // "PREFIX : <http://example.org/book/>\n"+// "SELECT ?title ?price\n" + // "{\n" + // " ?book :title ?title ; \n" + // " :price ?price . \n" + // "}\n" + // "BINDINGS ?book ?book {\n" + // "}"// ; try { parse(sparql, baseURI); fail("Expecting: " + VisitorException.class); } catch (Throwable t) { if (InnerCause.isInnerCause(t, VisitorException.class)) { if (log.isInfoEnabled()) log.info("Ignoring expected exception: " + t, t); return; } fail("Expecting: " + VisitorException.class); } } /** * Correct rejection test for the SPARQL 1.1 BINDINGS clause with too many * bindings in one binding set. * * <pre> * PREFIX : <http://example.org/book/> * SELECT ?title ?price * { * ?book :title ?title ; * :price ?price . * } * BINDINGS ?book { * (:book1) * (:book1 :book2) * } * </pre> */ public void test_bindings_009() throws MalformedQueryException, TokenMgrError, ParseException { final String sparql = "" + // "PREFIX : <http://example.org/book/>\n"+// "SELECT ?title ?price\n" + // "{\n" + // " ?book :title ?title ; \n" + // " :price ?price . \n" + // "}\n" + // "BINDINGS ?book {\n" + // " (:book1) \n"+// " (:book1 :book2) \n"+// "}"// ; try { parse(sparql, baseURI); fail("Expecting: " + VisitorException.class); } catch (Throwable t) { if (InnerCause.isInnerCause(t, VisitorException.class)) { if (log.isInfoEnabled()) log.info("Ignoring expected exception: " + t, t); return; } fail("Expecting: " + VisitorException.class); } } /** * Correct rejection test for the SPARQL 1.1 BINDINGS clause with too few * bindings in one binding set. * * <pre> * PREFIX : <http://example.org/book/> * SELECT ?title ?price * { * ?book :title ?title ; * :price ?price . * } * BINDINGS ?book ?title { * (:book1 :title1) * (:book1) * } * </pre> */ public void test_bindings_010() throws MalformedQueryException, TokenMgrError, ParseException { final String sparql = "" + // "PREFIX : <http://example.org/book/>\n"+// "SELECT ?title ?price\n" + // "{\n" + // " ?book :title ?title ; \n" + // " :price ?price . \n" + // "}\n" + // "BINDINGS ?book ?title {\n" + // " (:book1 :title1) \n"+// " (:book1) \n"+// "}"// ; try { parse(sparql, baseURI); fail("Expecting: " + VisitorException.class); } catch (Throwable t) { if (InnerCause.isInnerCause(t, VisitorException.class)) { if (log.isInfoEnabled()) log.info("Ignoring expected exception: " + t, t); return; } fail("Expecting: " + VisitorException.class); } } }