Fixes #131: Improved query builder support for "group by" and "having"
Project: http://git-wip-us.apache.org/repos/asf/metamodel/repo Commit: http://git-wip-us.apache.org/repos/asf/metamodel/commit/fe3aebe8 Tree: http://git-wip-us.apache.org/repos/asf/metamodel/tree/fe3aebe8 Diff: http://git-wip-us.apache.org/repos/asf/metamodel/diff/fe3aebe8 Branch: refs/heads/5.x Commit: fe3aebe865d0fa825c304e2f94f28a7c80ed467a Parents: b23085b Author: Kasper Sørensen <i.am.kasper.soren...@gmail.com> Authored: Sat Oct 8 23:54:24 2016 -0700 Committer: Kasper Sørensen <i.am.kasper.soren...@gmail.com> Committed: Sat Oct 8 23:54:24 2016 -0700 ---------------------------------------------------------------------- .../query/builder/GroupedQueryBuilder.java | 5 + .../builder/GroupedQueryBuilderCallback.java | 16 +++ .../query/builder/GroupedQueryBuilderImpl.java | 30 +++++- .../query/builder/HavingBuilderImpl.java | 100 +++++++++---------- .../query/builder/SatisfiedQueryBuilder.java | 4 +- .../query/builder/SyntaxExamplesTest.java | 5 + 6 files changed, 104 insertions(+), 56 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/metamodel/blob/fe3aebe8/core/src/main/java/org/apache/metamodel/query/builder/GroupedQueryBuilder.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/query/builder/GroupedQueryBuilder.java b/core/src/main/java/org/apache/metamodel/query/builder/GroupedQueryBuilder.java index 18b65d6..75a0c38 100644 --- a/core/src/main/java/org/apache/metamodel/query/builder/GroupedQueryBuilder.java +++ b/core/src/main/java/org/apache/metamodel/query/builder/GroupedQueryBuilder.java @@ -19,6 +19,7 @@ package org.apache.metamodel.query.builder; import org.apache.metamodel.query.FunctionType; +import org.apache.metamodel.query.SelectItem; import org.apache.metamodel.schema.Column; /** @@ -28,6 +29,10 @@ public interface GroupedQueryBuilder extends SatisfiedQueryBuilder<GroupedQueryBuilder> { public HavingBuilder having(FunctionType functionType, Column column); + + public HavingBuilder having(SelectItem selectItem); + + public HavingBuilder having(String columnExpression); public SatisfiedOrderByBuilder<GroupedQueryBuilder> orderBy( FunctionType function, Column column); http://git-wip-us.apache.org/repos/asf/metamodel/blob/fe3aebe8/core/src/main/java/org/apache/metamodel/query/builder/GroupedQueryBuilderCallback.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/query/builder/GroupedQueryBuilderCallback.java b/core/src/main/java/org/apache/metamodel/query/builder/GroupedQueryBuilderCallback.java index b5367ca..7a11ce2 100644 --- a/core/src/main/java/org/apache/metamodel/query/builder/GroupedQueryBuilderCallback.java +++ b/core/src/main/java/org/apache/metamodel/query/builder/GroupedQueryBuilderCallback.java @@ -26,6 +26,7 @@ import org.apache.metamodel.query.FilterItem; import org.apache.metamodel.query.FunctionType; import org.apache.metamodel.query.Query; import org.apache.metamodel.query.ScalarFunction; +import org.apache.metamodel.query.SelectItem; import org.apache.metamodel.schema.Column; import org.apache.metamodel.util.BaseObject; @@ -142,6 +143,21 @@ abstract class GroupedQueryBuilderCallback extends BaseObject implements Grouped } @Override + public HavingBuilder having(String columnExpression) { + return getQueryBuilder().having(columnExpression); + } + + @Override + public HavingBuilder having(SelectItem selectItem) { + return getQueryBuilder().having(selectItem); + } + + @Override + public GroupedQueryBuilder groupBy(String... columnNames) { + return getQueryBuilder().groupBy(columnNames); + } + + @Override public GroupedQueryBuilder groupBy(Column... columns) { getQueryBuilder().groupBy(columns); return this; http://git-wip-us.apache.org/repos/asf/metamodel/blob/fe3aebe8/core/src/main/java/org/apache/metamodel/query/builder/GroupedQueryBuilderImpl.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/query/builder/GroupedQueryBuilderImpl.java b/core/src/main/java/org/apache/metamodel/query/builder/GroupedQueryBuilderImpl.java index 0ea0098..d73ae8f 100644 --- a/core/src/main/java/org/apache/metamodel/query/builder/GroupedQueryBuilderImpl.java +++ b/core/src/main/java/org/apache/metamodel/query/builder/GroupedQueryBuilderImpl.java @@ -30,6 +30,7 @@ import org.apache.metamodel.query.FunctionType; import org.apache.metamodel.query.Query; import org.apache.metamodel.query.ScalarFunction; import org.apache.metamodel.query.SelectItem; +import org.apache.metamodel.query.parser.SelectItemParser; import org.apache.metamodel.schema.Column; import org.apache.metamodel.schema.Table; import org.apache.metamodel.util.BaseObject; @@ -96,7 +97,7 @@ final class GroupedQueryBuilderImpl extends BaseObject implements GroupedQueryBu @Override public ColumnSelectBuilder<GroupedQueryBuilder> select(String columnName) { - Column column = findColumn(columnName); + final Column column = findColumn(columnName); return select(column); } @@ -196,8 +197,8 @@ final class GroupedQueryBuilderImpl extends BaseObject implements GroupedQueryBu for (FromItem fromItem : fromItems) { final Table table = fromItem.getTable(); if (table != null) { - logger.debug("Table available in FROM item: {}. Column names: {}", table, - Arrays.toString(table.getColumnNames())); + logger.debug("Table available in FROM item: {}. Column names: {}", table, Arrays.toString(table + .getColumnNames())); } } } @@ -271,11 +272,17 @@ final class GroupedQueryBuilderImpl extends BaseObject implements GroupedQueryBu @Override public GroupedQueryBuilder groupBy(String columnName) { - Column column = findColumn(columnName); + final Column column = findColumn(columnName); return groupBy(column); } @Override + public GroupedQueryBuilder groupBy(String... columnNames) { + _query.groupBy(columnNames); + return this; + } + + @Override public GroupedQueryBuilder groupBy(Column... columns) { if (columns == null) { throw new IllegalArgumentException("columns cannot be null"); @@ -285,6 +292,21 @@ final class GroupedQueryBuilderImpl extends BaseObject implements GroupedQueryBu } @Override + public HavingBuilder having(String columnExpression) { + final SelectItemParser parser = new SelectItemParser(_query, false); + final SelectItem selectItem = parser.findSelectItem(columnExpression); + return having(selectItem); + } + + @Override + public HavingBuilder having(SelectItem selectItem) { + if (selectItem == null) { + throw new IllegalArgumentException("selectItem cannot be null"); + } + return new HavingBuilderImpl(selectItem, _query, this); + } + + @Override public HavingBuilder having(FunctionType function, Column column) { if (function == null) { throw new IllegalArgumentException("function cannot be null"); http://git-wip-us.apache.org/repos/asf/metamodel/blob/fe3aebe8/core/src/main/java/org/apache/metamodel/query/builder/HavingBuilderImpl.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/query/builder/HavingBuilderImpl.java b/core/src/main/java/org/apache/metamodel/query/builder/HavingBuilderImpl.java index 4406e65..41a2b11 100644 --- a/core/src/main/java/org/apache/metamodel/query/builder/HavingBuilderImpl.java +++ b/core/src/main/java/org/apache/metamodel/query/builder/HavingBuilderImpl.java @@ -27,61 +27,59 @@ import org.apache.metamodel.query.Query; import org.apache.metamodel.query.SelectItem; import org.apache.metamodel.schema.Column; -final class HavingBuilderImpl extends - AbstractQueryFilterBuilder<SatisfiedHavingBuilder> implements - HavingBuilder, SatisfiedHavingBuilder { +final class HavingBuilderImpl extends AbstractQueryFilterBuilder<SatisfiedHavingBuilder> implements + HavingBuilder, + SatisfiedHavingBuilder { - private final Query _query; - private final List<FilterItem> _orFilters; - private FilterItem _parentOrFilter; + private final Query _query; + private final List<FilterItem> _orFilters; + private FilterItem _parentOrFilter; - public HavingBuilderImpl(FunctionType function, Column column, Query query, - GroupedQueryBuilder queryBuilder) { - super(new SelectItem(function, column), queryBuilder); - _query = query; - _orFilters = new ArrayList<FilterItem>(); - } + public HavingBuilderImpl(SelectItem selectItem, Query query, GroupedQueryBuilder queryBuilder) { + super(selectItem, queryBuilder); + _query = query; + _orFilters = new ArrayList<FilterItem>(); + } - public HavingBuilderImpl(FunctionType function, Column column, Query query, - FilterItem parentOrFilter, List<FilterItem> orFilters, - GroupedQueryBuilder queryBuilder) { - super(new SelectItem(function, column), queryBuilder); - _query = query; - _orFilters = orFilters; - _parentOrFilter = parentOrFilter; - } + public HavingBuilderImpl(FunctionType function, Column column, Query query, GroupedQueryBuilder queryBuilder) { + this(new SelectItem(function, column), query, queryBuilder); + } - @Override - protected SatisfiedHavingBuilder applyFilter(FilterItem filter) { - if (_parentOrFilter == null) { - _query.having(filter); - } else { - if (_parentOrFilter.getChildItemCount() == 1) { - _query.getHavingClause().removeItem(_orFilters.get(0)); - _query.getHavingClause().addItem(_parentOrFilter); - } - } - _orFilters.add(filter); - return this; - } + public HavingBuilderImpl(FunctionType function, Column column, Query query, FilterItem parentOrFilter, + List<FilterItem> orFilters, GroupedQueryBuilder queryBuilder) { + this(function, column, query, queryBuilder); + } - @Override - public HavingBuilder or(FunctionType function, Column column) { - if (function == null) { - throw new IllegalArgumentException("function cannot be null"); - } - if (column == null) { - throw new IllegalArgumentException("column cannot be null"); - } - if (_parentOrFilter == null) { - _parentOrFilter = new FilterItem(_orFilters); - } - return new HavingBuilderImpl(function, column, _query, _parentOrFilter, - _orFilters, getQueryBuilder()); - } + @Override + protected SatisfiedHavingBuilder applyFilter(FilterItem filter) { + if (_parentOrFilter == null) { + _query.having(filter); + } else { + if (_parentOrFilter.getChildItemCount() == 1) { + _query.getHavingClause().removeItem(_orFilters.get(0)); + _query.getHavingClause().addItem(_parentOrFilter); + } + } + _orFilters.add(filter); + return this; + } - @Override - public HavingBuilder and(FunctionType function, Column column) { - return getQueryBuilder().having(function, column); - } + @Override + public HavingBuilder or(FunctionType function, Column column) { + if (function == null) { + throw new IllegalArgumentException("function cannot be null"); + } + if (column == null) { + throw new IllegalArgumentException("column cannot be null"); + } + if (_parentOrFilter == null) { + _parentOrFilter = new FilterItem(_orFilters); + } + return new HavingBuilderImpl(function, column, _query, _parentOrFilter, _orFilters, getQueryBuilder()); + } + + @Override + public HavingBuilder and(FunctionType function, Column column) { + return getQueryBuilder().having(function, column); + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/metamodel/blob/fe3aebe8/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedQueryBuilder.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedQueryBuilder.java b/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedQueryBuilder.java index e6b0670..f94ebdb 100644 --- a/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedQueryBuilder.java +++ b/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedQueryBuilder.java @@ -103,10 +103,12 @@ public interface SatisfiedQueryBuilder<B extends SatisfiedQueryBuilder<?>> { public SatisfiedOrderByBuilder<B> orderBy(Column column); public GroupedQueryBuilder groupBy(String columnName); + + public GroupedQueryBuilder groupBy(String ... columnNames); public GroupedQueryBuilder groupBy(Column column); - public B groupBy(Column... columns); + public GroupedQueryBuilder groupBy(Column... columns); /** * Gets the built query as a {@link Query} object. Typically the returned http://git-wip-us.apache.org/repos/asf/metamodel/blob/fe3aebe8/core/src/test/java/org/apache/metamodel/query/builder/SyntaxExamplesTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/metamodel/query/builder/SyntaxExamplesTest.java b/core/src/test/java/org/apache/metamodel/query/builder/SyntaxExamplesTest.java index 8876df9..af81801 100644 --- a/core/src/test/java/org/apache/metamodel/query/builder/SyntaxExamplesTest.java +++ b/core/src/test/java/org/apache/metamodel/query/builder/SyntaxExamplesTest.java @@ -70,6 +70,11 @@ public class SyntaxExamplesTest extends TestCase { dc.query().from(table1).selectCount().select(col1).groupBy(col1).having(FunctionType.SUM, col1).greaterThan(3) .orderBy(col1).asc(); } + + public void testMultiGroupByAndHaving() throws Exception { + dc.query().from(table1).select("foo", "bar", "COUNT(*)").groupBy("foo","bar").having("COUNT(*)").greaterThan(3) + .orderBy(col1).asc(); + } public void testMultipleTables() throws Exception { Query q = dc.query().from(table1).as("t1").and(table2).as("t2").select(col1).where(col1).greaterThan(col2)