Repository: metamodel Updated Branches: refs/heads/master 75e7698a1 -> 1b4cd55cf
METAMODEL-128: Fixed bug in DataSet ordering with aggregation function Fixes #13 Project: http://git-wip-us.apache.org/repos/asf/metamodel/repo Commit: http://git-wip-us.apache.org/repos/asf/metamodel/commit/1b4cd55c Tree: http://git-wip-us.apache.org/repos/asf/metamodel/tree/1b4cd55c Diff: http://git-wip-us.apache.org/repos/asf/metamodel/diff/1b4cd55c Branch: refs/heads/master Commit: 1b4cd55cf5a21620325ba711c1efd77d324e63a5 Parents: 75e7698 Author: Kasper Sørensen <[email protected]> Authored: Fri Apr 3 19:46:16 2015 +0200 Committer: Kasper Sørensen <[email protected]> Committed: Fri Apr 3 19:46:16 2015 +0200 ---------------------------------------------------------------------- CHANGES.md | 1 + .../org/apache/metamodel/MetaModelHelper.java | 16 +++++++++ .../query/parser/SelectItemParser.java | 15 +++++++-- .../QueryPostprocessDataContextTest.java | 21 ++++++++++++ .../metamodel/query/parser/QueryParserTest.java | 35 ++++++++++++-------- 5 files changed, 72 insertions(+), 16 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/metamodel/blob/1b4cd55c/CHANGES.md ---------------------------------------------------------------------- diff --git a/CHANGES.md b/CHANGES.md index 6725705..1b4db2e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,6 +4,7 @@ * [METAMODEL-93] - Added compatibility with Apache HBase version 1.0.0 * [METAMODEL-124] - Invoked ElasticSearch cross-version incompatible methods via reflection * [METAMODEL-125] - Added support for comma-separated select items in Query.select(String) method argument. + * [METAMODEL-128] - Fixed bug in DataSet ordering when aggregation functions are applied to non-JDBC modules. ### Apache MetaModel 4.3.2 http://git-wip-us.apache.org/repos/asf/metamodel/blob/1b4cd55c/core/src/main/java/org/apache/metamodel/MetaModelHelper.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/MetaModelHelper.java b/core/src/main/java/org/apache/metamodel/MetaModelHelper.java index bed4352..8b5d650 100644 --- a/core/src/main/java/org/apache/metamodel/MetaModelHelper.java +++ b/core/src/main/java/org/apache/metamodel/MetaModelHelper.java @@ -809,4 +809,20 @@ public final class MetaModelHelper { result.add((SelectItem) operand); } } + + /** + * This method returns the select item of the given alias name. + * + * @param query + * @return + */ + public static SelectItem getSelectItemByAlias(Query query, String alias) { + List<SelectItem> selectItems = query.getSelectClause().getItems(); + for (SelectItem selectItem : selectItems) { + if (selectItem.getAlias() != null && selectItem.getAlias().equals(alias)) { + return selectItem; + } + } + return null; + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/metamodel/blob/1b4cd55c/core/src/main/java/org/apache/metamodel/query/parser/SelectItemParser.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/query/parser/SelectItemParser.java b/core/src/main/java/org/apache/metamodel/query/parser/SelectItemParser.java index 84f6cc4..b2401c0 100644 --- a/core/src/main/java/org/apache/metamodel/query/parser/SelectItemParser.java +++ b/core/src/main/java/org/apache/metamodel/query/parser/SelectItemParser.java @@ -19,6 +19,7 @@ package org.apache.metamodel.query.parser; import org.apache.metamodel.MetaModelException; +import org.apache.metamodel.MetaModelHelper; import org.apache.metamodel.query.FromItem; import org.apache.metamodel.query.FunctionType; import org.apache.metamodel.query.Query; @@ -84,7 +85,7 @@ public final class SelectItemParser implements QueryPartProcessor { } } } - + /** * Finds/creates a SelectItem based on the given expression. Unlike the * {@link #parse(String, String)} method, this method will not actually add @@ -106,6 +107,8 @@ public final class SelectItemParser implements QueryPartProcessor { return SelectItem.getCountAllItem(); } + final String unmodifiedExpression = expression; + final FunctionType function; final int startParenthesis = expression.indexOf('('); if (startParenthesis > 0 && expression.endsWith(")")) { @@ -153,7 +156,8 @@ public final class SelectItemParser implements QueryPartProcessor { } } else if (fromItem.getSubQuery() != null) { final Query subQuery = fromItem.getSubQuery(); - final SelectItem subQuerySelectItem = new SelectItemParser(subQuery, _allowExpressionBasedSelectItems).findSelectItem(columnName); + final SelectItem subQuerySelectItem = new SelectItemParser(subQuery, _allowExpressionBasedSelectItems) + .findSelectItem(columnName); if (subQuerySelectItem == null) { return null; } @@ -161,6 +165,13 @@ public final class SelectItemParser implements QueryPartProcessor { } } + // if the expression is alias of some select item defined return that + // select item + final SelectItem aliasSelectItem = MetaModelHelper.getSelectItemByAlias(_query, unmodifiedExpression); + if (aliasSelectItem != null) { + return aliasSelectItem; + } + if (_allowExpressionBasedSelectItems) { return new SelectItem(function, expression, null); } http://git-wip-us.apache.org/repos/asf/metamodel/blob/1b4cd55c/core/src/test/java/org/apache/metamodel/QueryPostprocessDataContextTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/metamodel/QueryPostprocessDataContextTest.java b/core/src/test/java/org/apache/metamodel/QueryPostprocessDataContextTest.java index f32de56..4bcfd0a 100644 --- a/core/src/test/java/org/apache/metamodel/QueryPostprocessDataContextTest.java +++ b/core/src/test/java/org/apache/metamodel/QueryPostprocessDataContextTest.java @@ -1034,4 +1034,25 @@ public class QueryPostprocessDataContextTest extends MetaModelTestCase { assertEquals("SELECT contributor.contributor_id, contributor.name, contributor.country, COUNT(*)" + " FROM MetaModelSchema.contributor", query3.toString()); } + + public void testOrderOnAggregationValue() throws Exception { + MockDataContext dc = new MockDataContext("sch", "tab", "hello"); + + Query query = dc.parseQuery("SELECT MAX(baz) AS X FROM tab GROUP BY baz ORDER BY X"); + + DataSet ds = dc.executeQuery(query); + + List<String> values = new ArrayList<String>(); + + while (ds.next()) { + final String value = (String) ds.getRow().getValue(0); + values.add(value); + } + + ds.close(); + + // this should be alphabetically sorted + assertEquals("[hello, world]", values.toString()); + } + } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/metamodel/blob/1b4cd55c/core/src/test/java/org/apache/metamodel/query/parser/QueryParserTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/metamodel/query/parser/QueryParserTest.java b/core/src/test/java/org/apache/metamodel/query/parser/QueryParserTest.java index 9edf8a2..a6c2e9e 100644 --- a/core/src/test/java/org/apache/metamodel/query/parser/QueryParserTest.java +++ b/core/src/test/java/org/apache/metamodel/query/parser/QueryParserTest.java @@ -88,7 +88,14 @@ public class QueryParserTest extends TestCase { assertEquals("SELECT tbl.foo AS f FROM sch.tbl", q.toSql()); q = MetaModelHelper.parseQuery(dc, "SELECT a.foo AS foobarbaz FROM sch.tbl a WHERE foobarbaz = '123'"); - assertEquals("SELECT a.foo AS foobarbaz FROM sch.tbl a WHERE foobarbaz = '123'", q.toSql()); + assertEquals("SELECT a.foo AS foobarbaz FROM sch.tbl a WHERE a.foo = '123'", q.toSql()); + + // assert that the referred "foobarbaz" is in fact the same select item + // (that's not visible from the toSql() call since there + // WhereItem.toSql() method will not use the alias) + SelectItem selectItem1 = q.getSelectClause().getItem(0); + SelectItem selectItem2 = q.getWhereClause().getItem(0).getSelectItem(); + assertSame(selectItem1, selectItem2); } public void testSelectDistinct() throws Exception { @@ -172,29 +179,29 @@ public class QueryParserTest extends TestCase { assertEquals("baz", whereClause.getItem(0).getOperand()); assertEquals(Integer.class, whereClause.getItem(1).getOperand().getClass()); } - + public void testWhereStringEscaped() throws Exception { Query q = MetaModelHelper.parseQuery(dc, "SELECT foo FROM sch.tbl WHERE bar = 'ba\\'z'"); assertEquals("SELECT tbl.foo FROM sch.tbl WHERE tbl.bar = 'ba'z'", q.toSql()); } - + public void testWhereOperandIsBoolean() throws Exception { - // set 'baz' column to an integer column (to influence query generation) + // set 'baz' column to an integer column (to influence query generation) MutableColumn col = (MutableColumn) dc.getColumnByQualifiedLabel("tbl.baz"); col.setType(ColumnType.BOOLEAN); - + Query q = MetaModelHelper.parseQuery(dc, "SELECT foo FROM sch.tbl WHERE baz = TRUE"); assertEquals("SELECT tbl.foo FROM sch.tbl WHERE tbl.baz = TRUE", q.toSql()); } - + public void testWhereOperandIsDate() throws Exception { // set 'baz' column to an integer column (to influence query generation) - MutableColumn col = (MutableColumn) dc.getColumnByQualifiedLabel("tbl.baz"); - col.setType(ColumnType.TIME); - - Query q = MetaModelHelper.parseQuery(dc, "SELECT foo FROM sch.tbl WHERE baz = 10:24"); - assertEquals("SELECT tbl.foo FROM sch.tbl WHERE tbl.baz = TIME '10:24:00'", q.toSql()); - } + MutableColumn col = (MutableColumn) dc.getColumnByQualifiedLabel("tbl.baz"); + col.setType(ColumnType.TIME); + + Query q = MetaModelHelper.parseQuery(dc, "SELECT foo FROM sch.tbl WHERE baz = 10:24"); + assertEquals("SELECT tbl.foo FROM sch.tbl WHERE tbl.baz = TIME '10:24:00'", q.toSql()); + } public void testCoumpoundWhereClause() throws Exception { Query q = MetaModelHelper @@ -300,7 +307,7 @@ public class QueryParserTest extends TestCase { Query q = MetaModelHelper.parseQuery(dc, "SELECT f.foo AS fo FROM (SELECT * FROM sch.tbl) f"); assertEquals("SELECT f.foo AS fo FROM (SELECT tbl.foo, tbl.bar, tbl.baz FROM sch.tbl) f", q.toSql()); } - + public void testSelectEverythingFromSubQuery() throws Exception { Query q = MetaModelHelper.parseQuery(dc, "SELECT * FROM (SELECT foo, bar FROM sch.tbl) f"); assertEquals("SELECT f.foo, f.bar FROM (SELECT tbl.foo, tbl.bar FROM sch.tbl) f", q.toSql()); @@ -311,7 +318,7 @@ public class QueryParserTest extends TestCase { assertEquals("[0, 7]", Arrays.toString(qp.indexesOf("SELECT ", null))); assertEquals("[10, 16]", Arrays.toString(qp.indexesOf(" FROM ", null))); } - + public void testGetIndicesIgnoreWhiteSpaceAndCaseDifferences() throws Exception { QueryParser qp = new QueryParser(dc, " \t\r\n select ... from ... BAR BAZ"); assertEquals("[0, 7]", Arrays.toString(qp.indexesOf("SELECT ", null)));
