From 2aa4b19c2999eb4c3068f9481ac45895e2679a9c Mon Sep 17 00:00:00 2001 From: Igor Kim Date: Thu, 29 Aug 2019 03:03:42 +0500 Subject: [PATCH] Fix non-aggregate variable in HAVING of named subquery Bug: T165559 Change-Id: Ie6fdb3b62b82cb4e87b1d18cba7cd494e5b5ebe6 --- .../rdf/sparql/ast/StaticAnalysis.java | 15 ++- .../rdf/sail/webapp/Test_Ticket_T165559.java | 106 ++++++++++++++++++ 2 files changed, 119 insertions(+), 2 deletions(-) create mode 100644 bigdata-sails-test/src/test/java/com/bigdata/rdf/sail/webapp/Test_Ticket_T165559.java diff --git a/bigdata-core/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/StaticAnalysis.java b/bigdata-core/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/StaticAnalysis.java index 1f139fd5ae..865a5ae9b0 100644 --- a/bigdata-core/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/StaticAnalysis.java +++ b/bigdata-core/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/StaticAnalysis.java @@ -2546,8 +2546,19 @@ public static boolean isAggregate(final ProjectionNode projection, if (groupBy != null && !groupBy.isEmpty()) return true; - if (having != null && !having.isEmpty()) - return true; + // Need to check if HAVING expressions are indeed aggregates, + // as fastRangeCount might be used instead of real count aggregation + // resulting in false positive check while using named subquery with aggregates + // in com.bigdata.bop.solutions.GroupByState.isAggregate + // Ref: Test_Ticket_T165559 + if (having != null && !having.isEmpty()) { + for (BOp arg: having.args()) { + if (arg instanceof IValueExpressionNode && + isAggregateExpressionNode((IValueExpressionNode) arg)) { + return true; + } + } + } if (projection != null) { diff --git a/bigdata-sails-test/src/test/java/com/bigdata/rdf/sail/webapp/Test_Ticket_T165559.java b/bigdata-sails-test/src/test/java/com/bigdata/rdf/sail/webapp/Test_Ticket_T165559.java new file mode 100644 index 0000000000..2f1248b6a9 --- /dev/null +++ b/bigdata-sails-test/src/test/java/com/bigdata/rdf/sail/webapp/Test_Ticket_T165559.java @@ -0,0 +1,106 @@ +/* +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 +*/ + + +package com.bigdata.rdf.sail.webapp; + +import junit.framework.Test; + +import java.util.Arrays; + +import org.openrdf.model.Statement; +import org.openrdf.model.URI; +import org.openrdf.model.impl.URIImpl; +import org.openrdf.model.impl.ValueFactoryImpl; +import org.openrdf.model.vocabulary.RDF; +import org.openrdf.query.QueryLanguage; +import org.openrdf.query.TupleQuery; +import org.openrdf.query.TupleQueryResult; + +import com.bigdata.journal.IIndexManager; +import com.bigdata.rdf.sail.webapp.client.RemoteRepository.AddOp; +import com.bigdata.rdf.sail.webapp.client.RemoteRepository.RemoveOp; + +/** + * HAVING in named subquery results in “non-aggregate variable in select expression” error + * @See https://phabricator.wikimedia.org/T165559 + * + */ +public class Test_Ticket_T165559 extends + AbstractTestNanoSparqlClient { + + public Test_Ticket_T165559() { + + } + + public Test_Ticket_T165559(final String name) { + + super(name); + + } + + public static Test suite() { + + return ProxySuiteHelper.suiteWhenStandalone(Test_Ticket_T165559.class, + "test.*", TestMode.triples + ); + + } + + /** + * Test supposed to check if constants .. will be resolved + */ + public void test_havingInNamedSubquery_T165559() throws Exception { + // Clear DB per task description (Executing the query over the empty database) + m_repo.remove(new RemoveOp(null, null, null)); + + final URI s = new URIImpl("t:Q165559"); + final URI p2 = RDF.TYPE; + final URI t = new URIImpl("schema:Dataset"); + + ValueFactoryImpl vf = ValueFactoryImpl.getInstance(); + final Statement[] a = new Statement[] { + vf.createStatement(s, p2, t) + }; + + final AddOp addOp = new AddOp(Arrays.asList(a)); + + m_repo.add(addOp); + + String query = "SELECT ?x WITH {\n" + + " SELECT ?x (COUNT(*) AS ?count) WHERE {\n" + + " ?x a .\n" + + " }\n" + + " GROUP BY ?x\n" + + " HAVING(?count > 0)\n" + + "} AS %subSelect WHERE {\n" + + " INCLUDE %subSelect . \n" + + "}"; + + final TupleQuery tq = m_repo.getBigdataSailRemoteRepository().getConnection().prepareTupleQuery(QueryLanguage.SPARQL, query, null); + final TupleQueryResult tqr = tq.evaluate(); + try { + int count = 0; + while (tqr.hasNext()) { + System.out.println(tqr.next()); + count++; + } + assertEquals(1,count); // asserting successful execution of the query, as it was failing while parsing + } finally { + tqr.close(); + } + } + +}