/*
* This file is part of jdbc4sparql jsqlparser implementation.
*
* jdbc4sparql jsqlparser implementation is free software: you can redistribute
* it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* jdbc4sparql jsqlparser implementation 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with jdbc4sparql jsqlparser implementation. If not, see
* <http://www.gnu.org/licenses/>.
*/
package org.xenei.jdbc4sparql.sparql.visitor;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.Arrays;
import java.util.List;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.xenei.jdbc4sparql.iface.name.ColumnName;
import org.xenei.jdbc4sparql.iface.name.NameSegments;
import org.xenei.jdbc4sparql.impl.NameUtils;
import org.xenei.jdbc4sparql.sparql.parser.jsqlparser.SparqlVisitor;
import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.sparql.core.Var;
import com.hp.hpl.jena.sparql.expr.E_Equals;
import com.hp.hpl.jena.sparql.expr.E_Function;
import com.hp.hpl.jena.sparql.expr.E_NotEquals;
import com.hp.hpl.jena.sparql.expr.Expr;
import com.hp.hpl.jena.sparql.expr.ExprAggregator;
import com.hp.hpl.jena.sparql.expr.ExprVar;
import com.hp.hpl.jena.sparql.expr.nodevalue.NodeValueString;
import com.hp.hpl.jena.sparql.syntax.Element;
import com.hp.hpl.jena.sparql.syntax.ElementBind;
import com.hp.hpl.jena.sparql.syntax.ElementFilter;
import com.hp.hpl.jena.sparql.syntax.ElementOptional;
import com.hp.hpl.jena.sparql.syntax.ElementPathBlock;
import com.hp.hpl.jena.sparql.syntax.ElementService;
import com.hp.hpl.jena.sparql.syntax.ElementSubQuery;
public class RemoteSparqlVisitorTest extends AbstractSparqlVisitorTest {
private static final String SERVICE_URI = "http://example.com/sparql";
@Override
@Before
public void setup() throws Exception {
super.setup();
final Property p = model.createProperty(
"http://org.xenei.jdbc4sparql/entity/Catalog#",
"sparqlEndpoint");
catalog.getResource().addProperty(p, SERVICE_URI);
assertTrue("Catalog was not set to service", catalog.isService());
// recreate the visitor to handle service catalog
sv = new SparqlVisitor(catalogs, parser, catalog, schema);
}
@Test
public void testInnerJoinParse() throws Exception {
final String fmt = "%s" + NameUtils.SPARQL_DOT + "%s";
final String[] colNames = {
String.format(fmt, "foo", "StringCol"),
String.format(fmt, "foo", "NullableStringCol"),
String.format(fmt, "foo", "IntCol"), "NullableIntCol",
String.format(fmt, "bar", "BarStringCol"),
String.format(fmt, "bar", "BarNullableStringCol"),
String.format(fmt, "bar", "BarIntCol")
};
final Query q = getQuery("SELECT * FROM foo inner join bar using (NullableIntCol)");
tests.put(ElementBind.class, 7);
tests.put(ElementFilter.class, 3);
tests.put(ElementService.class, 1);
results = validate(q, tests);
final List<Var> vLst = q.getProjectVars();
Assert.assertEquals(7, vLst.size());
for (final Var v : vLst) {
Assert.assertTrue(Arrays.asList(colNames).contains(v.getName()));
}
final ElementService service = (ElementService) results
.get(ElementService.class).lst.get(0);
final Query q2 = ((ElementSubQuery) service.getElement()).getQuery();
final List<Element> bindList = results.get(ElementBind.class).lst;
for (final Element el : bindList) {
final ElementBind bind = (ElementBind) el;
Assert.assertTrue("result vars missing bind var " + bind.getVar(),
q.getProjectVars().contains(bind.getVar()));
final E_Function func = (E_Function) bind.getExpr();
Assert.assertTrue(
"service vars missing bind var " + bind.getExpr(),
q2.getProjectVars().contains(
((ExprVar) func.getArg(1)).asVar()));
}
}
@Test
public void testMethodParse() throws Exception {
final Query q = getQuery("SELECT count( IntCol ) FROM foo");
tests.put(ElementBind.class, 0);
tests.put(ElementFilter.class, 1);
tests.put(ElementService.class, 1);
results = validate(q, tests);
final ElementService service = (ElementService) results
.get(ElementService.class).lst.get(0);
final Query q2 = ((ElementSubQuery) service.getElement()).getQuery();
assertEquals(1, q.getProjectVars().size());
final ExprAggregator e = (ExprAggregator) q.getProject().getExpr(
q.getProjectVars().get(0));
final Var v2 = e.getAggregator().getExpr().asVar();
assertTrue(v2.toString() + " missing from service call", q2
.getProjectVars().contains(v2));
}
@Test
public void testMethodWithAliasParse() throws Exception {
final Query q = getQuery("SELECT count( IntCol ) AS bar FROM foo");
tests.put(ElementBind.class, 0);
tests.put(ElementFilter.class, 1);
tests.put(ElementService.class, 1);
results = validate(q, tests);
Assert.assertEquals(1, q.getProject().size());
Assert.assertEquals(1, q.getProjectVars().size());
Assert.assertEquals("bar", q.getProjectVars().get(0).getVarName());
final ElementService service = (ElementService) results
.get(ElementService.class).lst.get(0);
final Query q2 = ((ElementSubQuery) service.getElement()).getQuery();
assertEquals(1, q.getProjectVars().size());
final ExprAggregator e = (ExprAggregator) q.getProject().getExpr(
q.getProjectVars().get(0));
final Var v2 = e.getAggregator().getExpr().asVar();
assertTrue(v2.toString() + " missing from service call", q2
.getProjectVars().contains(v2));
}
@Test
public void testNoColParse() throws Exception {
final String[] colNames = {
"StringCol", "NullableStringCol", "IntCol", "NullableIntCol"
};
final Query q = getQuery("SELECT * FROM foo");
tests.put(ElementBind.class, 4);
tests.put(ElementFilter.class, 1);
tests.put(ElementOptional.class, 2);
tests.put(ElementService.class, 1);
results = validate(q, tests);
final List<Var> vLst = q.getProjectVars();
Assert.assertEquals(4, vLst.size());
for (final Var v : vLst) {
Assert.assertTrue(Arrays.asList(colNames).contains(v.getName()));
}
for (final Element el : results.get(ElementBind.class).lst) {
final ElementBind bind = (ElementBind) el;
Assert.assertTrue(q.getProjectVars().contains(bind.getVar()));
}
final ElementService srv = (ElementService) results
.get(ElementService.class).lst.get(0);
final ElementSubQuery esq = (ElementSubQuery) srv.getElement();
final List<Var> vars = esq.getQuery().getProjectVars();
Assert.assertEquals(4, vars.size());
}
@Test
public void testSpecColParse() throws Exception {
final Query q = getQuery("SELECT StringCol FROM foo");
tests.put(ElementBind.class, 1);
tests.put(ElementFilter.class, 1);
tests.put(ElementOptional.class, 2);
tests.put(ElementService.class, 1);
results = validate(q, tests);
final List<Var> vLst = q.getProjectVars();
Assert.assertEquals(1, vLst.size());
Assert.assertEquals(Var.alloc("StringCol"), vLst.get(0));
final Element el = results.get(ElementBind.class).lst.get(0);
final ElementBind eb = (ElementBind) el;
Assert.assertEquals("StringCol", eb.getVar().getName());
final ElementService srv = (ElementService) results
.get(ElementService.class).lst.get(0);
final ElementSubQuery esq = (ElementSubQuery) srv.getElement();
final List<Var> vars = esq.getQuery().getProjectVars();
// all 4 columns in foo
Assert.assertEquals(4, vars.size());
}
@Test
public void testSpecColWithAliasParse() throws Exception {
final Query q = getQuery("SELECT StringCol AS bar FROM foo");
tests.put(ElementBind.class, 1);
tests.put(ElementFilter.class, 1);
tests.put(ElementOptional.class, 2);
tests.put(ElementService.class, 1);
results = validate(q, tests);
final List<Var> vLst = q.getProjectVars();
Assert.assertEquals(1, vLst.size());
Assert.assertEquals(Var.alloc("bar"), vLst.get(0));
final ElementBind eb = (ElementBind) results.get(ElementBind.class).lst
.get(0);
final String name = eb.getVar().getName();
Assert.assertEquals("bar", name);
}
@Test
public void testSpecColWithEqnParse() throws Exception {
final Query q = getQuery("SELECT StringCol FROM foo WHERE StringCol != 'baz'");
tests.put(ElementBind.class, 1);
tests.put(ElementFilter.class, 2);
tests.put(ElementOptional.class, 2);
tests.put(ElementService.class, 1);
results = validate(q, tests);
final ElementBind eb = (ElementBind) results.get(ElementBind.class).lst
.get(0);
final String name = eb.getVar().getName();
Assert.assertEquals("StringCol", name);
final ElementService srv = (ElementService) results
.get(ElementService.class).lst.get(0);
final ElementSubQuery esq = (ElementSubQuery) srv.getElement();
final List<Var> vars = esq.getQuery().getProjectVars();
Assert.assertEquals(4, vars.size());
tests.clear();
tests.put(ElementFilter.class, 1);
results = validate(srv.getElement(), tests);
final Expr expr = ((ElementFilter) results.get(ElementFilter.class).lst
.get(0)).getExpr();
Assert.assertTrue(expr instanceof E_NotEquals);
final E_NotEquals expr2 = (E_NotEquals) expr;
Assert.assertEquals("v_571a89fd_0385_38d9_9ef2_c37d2542d0ad",
((ExprVar) (expr2.getArg1())).getVarName());
Assert.assertEquals("baz",
((NodeValueString) (expr2.getArg2())).asString());
final List<Var> vLst = q.getProjectVars();
Assert.assertEquals(1, vLst.size());
Assert.assertEquals(Var.alloc("StringCol"), vLst.get(0));
}
@Test
public void testTableAliasParse() throws Exception {
final Query q = getQuery("SELECT StringCol FROM foo bar WHERE StringCol != 'baz'");
tests.put(ElementBind.class, 1);
tests.put(ElementFilter.class, 2);
tests.put(ElementOptional.class, 2);
tests.put(ElementService.class, 1);
tests.put(ElementPathBlock.class, 4);
results = validate(q, tests);
final List<Var> vLst = q.getProjectVars();
Assert.assertEquals(1, vLst.size());
Assert.assertEquals(Var.alloc("StringCol"), vLst.get(0));
// 2 required columns
final String[] names = {
"StringCol", "IntCol"
};
for (final Element el : results.get(ElementBind.class).lst) {
final ElementBind eb = (ElementBind) el;
final String name = eb.getVar().getName();
Assert.assertTrue(Arrays.asList(names).contains(name));
}
// should be the first one
final Expr expr = ((ElementFilter) results.get(ElementFilter.class).lst
.get(0)).getExpr();
Assert.assertTrue(expr instanceof E_NotEquals);
final E_NotEquals expr2 = (E_NotEquals) expr;
Assert.assertEquals("v_c7b696e2_e6e6_372c_807d_51154bb155e1",
((ExprVar) (expr2.getArg1())).getVarName());
Assert.assertEquals("baz",
((NodeValueString) (expr2.getArg2())).asString());
verifyTable(results.get(ElementPathBlock.class),
"v_31c94ccf_f177_3e10_a2f3_e790f85b33c5");
}
@Test
public void testTwoTableJoin() throws Exception {
final String[] columnNames = {
"foo" + NameUtils.SPARQL_DOT + "IntCol",
"foo" + NameUtils.SPARQL_DOT + "StringCol",
"foo" + NameUtils.SPARQL_DOT + "NullableStringCol",
"foo" + NameUtils.SPARQL_DOT + "NullableIntCol",
"bar" + NameUtils.SPARQL_DOT + "BarStringCol",
"bar" + NameUtils.SPARQL_DOT + "BarNullableStringCol",
"bar" + NameUtils.SPARQL_DOT + "BarIntCol",
"bar" + NameUtils.SPARQL_DOT + "NullableIntCol"
};
final Query q = getQuery("SELECT * FROM foo, bar WHERE foo.IntCol = bar.BarIntCol");
tests.put(ElementBind.class, columnNames.length);
tests.put(ElementFilter.class, 3);
tests.put(ElementOptional.class, 4);
tests.put(ElementService.class, 1);
results = validate(q, tests);
final List<Var> vLst = q.getProjectVars();
Assert.assertEquals(columnNames.length, vLst.size());
for (final Var v : vLst) {
final ColumnName tn = ColumnName.getNameInstance("testCatalog",
"testSchema", "table", v.getName());
tn.setUsedSegments(NameSegments.FFTT);
Assert.assertTrue("missing " + tn.getSPARQLName(),
Arrays.asList(columnNames).contains(tn.getSPARQLName()));
}
final Expr expr = ((ElementFilter) results.get(ElementFilter.class).lst
.get(0)).getExpr();
Assert.assertTrue(expr instanceof E_Equals);
final E_Equals expr2 = (E_Equals) expr;
Assert.assertEquals("v_f87609c4_9dab_3bf7_8522_ccd46fa4e808",
((ExprVar) (expr2.getArg1())).getVarName());
Assert.assertEquals("v_1f5a248c_0097_30a6_b600_444a479c14b4",
((ExprVar) (expr2.getArg2())).getVarName());
}
}