diff --git a/src/main/java/org/mybatis/dynamic/sql/SqlBuilder.java b/src/main/java/org/mybatis/dynamic/sql/SqlBuilder.java index 5bccd05eb..8152e6c93 100644 --- a/src/main/java/org/mybatis/dynamic/sql/SqlBuilder.java +++ b/src/main/java/org/mybatis/dynamic/sql/SqlBuilder.java @@ -331,19 +331,19 @@ static CountDistinct countDistinct(BasicColumn column) { return CountDistinct.of(column); } - static Max max(BasicColumn column) { + static Max max(BindableColumn column) { return Max.of(column); } - static Min min(BasicColumn column) { + static Min min(BindableColumn column) { return Min.of(column); } - static Avg avg(BasicColumn column) { + static Avg avg(BindableColumn column) { return Avg.of(column); } - static Sum sum(BasicColumn column) { + static Sum sum(BindableColumn column) { return Sum.of(column); } diff --git a/src/main/java/org/mybatis/dynamic/sql/select/aggregate/AbstractAggregate.java b/src/main/java/org/mybatis/dynamic/sql/select/aggregate/AbstractAggregate.java index fb3832a49..b966c95e3 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/aggregate/AbstractAggregate.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/aggregate/AbstractAggregate.java @@ -23,11 +23,15 @@ /** * This class is the base class for aggregate functions. - * + * + * @deprecated in favor of {@link org.mybatis.dynamic.sql.select.function.AbstractUniTypeFunction} as there is + * virtually no difference between an aggregate and a function + * * @author Jeff Butler * * @param the subclass type */ +@Deprecated public abstract class AbstractAggregate> implements BasicColumn { protected final BasicColumn column; protected String alias; diff --git a/src/main/java/org/mybatis/dynamic/sql/select/aggregate/AbstractCount.java b/src/main/java/org/mybatis/dynamic/sql/select/aggregate/AbstractCount.java new file mode 100644 index 000000000..9c0c11a3e --- /dev/null +++ b/src/main/java/org/mybatis/dynamic/sql/select/aggregate/AbstractCount.java @@ -0,0 +1,46 @@ +/* + * Copyright 2016-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.dynamic.sql.select.aggregate; + +import java.util.Optional; +import org.mybatis.dynamic.sql.BindableColumn; + +/** + * Count functions are implemented differently than the other aggregates. This is primarily to preserve + * backwards compatibility. Count functions are configured as BindableColumns of type Long + * as it is assumed that the count functions always return a number. + * + * @param the subtype of this class + */ +public abstract class AbstractCount> implements BindableColumn { + private final String alias; + + protected AbstractCount(String alias) { + this.alias = alias; + } + + @Override + public Optional alias() { + return Optional.ofNullable(alias); + } + + @Override + public T as(String alias) { + return copyWithAlias(alias); + } + + protected abstract T copyWithAlias(String alias); +} diff --git a/src/main/java/org/mybatis/dynamic/sql/select/aggregate/Avg.java b/src/main/java/org/mybatis/dynamic/sql/select/aggregate/Avg.java index 6c5fa85a8..4da9a100a 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/aggregate/Avg.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/aggregate/Avg.java @@ -15,25 +15,27 @@ */ package org.mybatis.dynamic.sql.select.aggregate; -import org.mybatis.dynamic.sql.BasicColumn; +import org.mybatis.dynamic.sql.BindableColumn; +import org.mybatis.dynamic.sql.render.TableAliasCalculator; +import org.mybatis.dynamic.sql.select.function.AbstractUniTypeFunction; -public class Avg extends AbstractAggregate { +public class Avg extends AbstractUniTypeFunction> { - private Avg(BasicColumn column) { + private Avg(BindableColumn column) { super(column); } - + @Override - protected String render(String columnName) { - return "avg(" + columnName + ")"; //$NON-NLS-1$ //$NON-NLS-2$ + public String renderWithTableAlias(TableAliasCalculator tableAliasCalculator) { + return "avg(" + column.renderWithTableAlias(tableAliasCalculator) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ } @Override - protected Avg copy() { - return new Avg(column); + protected Avg copy() { + return new Avg<>(column); } - public static Avg of(BasicColumn column) { - return new Avg(column); + public static Avg of(BindableColumn column) { + return new Avg<>(column); } } diff --git a/src/main/java/org/mybatis/dynamic/sql/select/aggregate/Count.java b/src/main/java/org/mybatis/dynamic/sql/select/aggregate/Count.java index 915ff31ab..7c752d530 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/aggregate/Count.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/aggregate/Count.java @@ -15,25 +15,31 @@ */ package org.mybatis.dynamic.sql.select.aggregate; +import java.util.Objects; + import org.mybatis.dynamic.sql.BasicColumn; +import org.mybatis.dynamic.sql.render.TableAliasCalculator; + +public class Count extends AbstractCount { + + private final BasicColumn column; -public class Count extends AbstractAggregate { - - private Count(BasicColumn column) { - super(column); + private Count(BasicColumn column, String alias) { + super(alias); + this.column = Objects.requireNonNull(column); } - + @Override - protected String render(String columnName) { - return "count(" + columnName + ")"; //$NON-NLS-1$ //$NON-NLS-2$ + public String renderWithTableAlias(TableAliasCalculator tableAliasCalculator) { + return "count(" + column.renderWithTableAlias(tableAliasCalculator) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ } @Override - protected Count copy() { - return new Count(column); + protected Count copyWithAlias(String alias) { + return new Count(column, alias); } - + public static Count of(BasicColumn column) { - return new Count(column); + return new Count(column, null); } } diff --git a/src/main/java/org/mybatis/dynamic/sql/select/aggregate/CountAll.java b/src/main/java/org/mybatis/dynamic/sql/select/aggregate/CountAll.java index 25a15310f..cc9bf1d1f 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/aggregate/CountAll.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/aggregate/CountAll.java @@ -15,40 +15,25 @@ */ package org.mybatis.dynamic.sql.select.aggregate; -import java.util.Optional; - -import org.mybatis.dynamic.sql.BasicColumn; import org.mybatis.dynamic.sql.render.TableAliasCalculator; -/** - * CountAll seems like the other aggregates, but it is special because there is no column. - * Rather than dealing with a useless and confusing abstraction, we simply implement - * BasicColumn directly. - * - * @author Jeff Butler - */ -public class CountAll implements BasicColumn { - - private String alias; +public class CountAll extends AbstractCount { public CountAll() { - super(); + super(null); } - @Override - public String renderWithTableAlias(TableAliasCalculator tableAliasCalculator) { - return "count(*)"; //$NON-NLS-1$ + private CountAll(String alias) { + super(alias); } @Override - public Optional alias() { - return Optional.ofNullable(alias); + public String renderWithTableAlias(TableAliasCalculator tableAliasCalculator) { + return "count(*)"; //$NON-NLS-1$ } @Override - public CountAll as(String alias) { - CountAll copy = new CountAll(); - copy.alias = alias; - return copy; + protected CountAll copyWithAlias(String alias) { + return new CountAll(alias); } } diff --git a/src/main/java/org/mybatis/dynamic/sql/select/aggregate/CountDistinct.java b/src/main/java/org/mybatis/dynamic/sql/select/aggregate/CountDistinct.java index f689811f6..f9527ab6b 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/aggregate/CountDistinct.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/aggregate/CountDistinct.java @@ -15,25 +15,31 @@ */ package org.mybatis.dynamic.sql.select.aggregate; +import java.util.Objects; + import org.mybatis.dynamic.sql.BasicColumn; +import org.mybatis.dynamic.sql.render.TableAliasCalculator; + +public class CountDistinct extends AbstractCount { + + private final BasicColumn column; -public class CountDistinct extends AbstractAggregate { - - private CountDistinct(BasicColumn column) { - super(column); + private CountDistinct(BasicColumn column, String alias) { + super(alias); + this.column = Objects.requireNonNull(column); } - + @Override - protected String render(String columnName) { - return "count(distinct " + columnName + ")"; //$NON-NLS-1$ //$NON-NLS-2$ + public String renderWithTableAlias(TableAliasCalculator tableAliasCalculator) { + return "count(distinct " + column.renderWithTableAlias(tableAliasCalculator) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ } @Override - protected CountDistinct copy() { - return new CountDistinct(column); + public CountDistinct copyWithAlias(String alias) { + return new CountDistinct(column, alias); } - + public static CountDistinct of(BasicColumn column) { - return new CountDistinct(column); + return new CountDistinct(column, null); } } diff --git a/src/main/java/org/mybatis/dynamic/sql/select/aggregate/Max.java b/src/main/java/org/mybatis/dynamic/sql/select/aggregate/Max.java index 86bbce1de..dfaa8df6d 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/aggregate/Max.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/aggregate/Max.java @@ -15,25 +15,27 @@ */ package org.mybatis.dynamic.sql.select.aggregate; -import org.mybatis.dynamic.sql.BasicColumn; +import org.mybatis.dynamic.sql.BindableColumn; +import org.mybatis.dynamic.sql.render.TableAliasCalculator; +import org.mybatis.dynamic.sql.select.function.AbstractUniTypeFunction; -public class Max extends AbstractAggregate { +public class Max extends AbstractUniTypeFunction> { - private Max(BasicColumn column) { + private Max(BindableColumn column) { super(column); } - + @Override - protected String render(String columnName) { - return "max(" + columnName + ")"; //$NON-NLS-1$ //$NON-NLS-2$ + public String renderWithTableAlias(TableAliasCalculator tableAliasCalculator) { + return "max(" + column.renderWithTableAlias(tableAliasCalculator) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ } @Override - protected Max copy() { - return new Max(column); + protected Max copy() { + return new Max<>(column); } - public static Max of(BasicColumn column) { - return new Max(column); + public static Max of(BindableColumn column) { + return new Max<>(column); } } diff --git a/src/main/java/org/mybatis/dynamic/sql/select/aggregate/Min.java b/src/main/java/org/mybatis/dynamic/sql/select/aggregate/Min.java index 97b2c6390..25bf6e6cb 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/aggregate/Min.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/aggregate/Min.java @@ -15,25 +15,27 @@ */ package org.mybatis.dynamic.sql.select.aggregate; -import org.mybatis.dynamic.sql.BasicColumn; +import org.mybatis.dynamic.sql.BindableColumn; +import org.mybatis.dynamic.sql.render.TableAliasCalculator; +import org.mybatis.dynamic.sql.select.function.AbstractUniTypeFunction; -public class Min extends AbstractAggregate { +public class Min extends AbstractUniTypeFunction> { - private Min(BasicColumn column) { + private Min(BindableColumn column) { super(column); } - + @Override - protected String render(String columnName) { - return "min(" + columnName + ")"; //$NON-NLS-1$ //$NON-NLS-2$ + public String renderWithTableAlias(TableAliasCalculator tableAliasCalculator) { + return "min(" + column.renderWithTableAlias(tableAliasCalculator) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ } @Override - protected Min copy() { - return new Min(column); + protected Min copy() { + return new Min<>(column); } - public static Min of(BasicColumn column) { - return new Min(column); + public static Min of(BindableColumn column) { + return new Min<>(column); } } diff --git a/src/main/java/org/mybatis/dynamic/sql/select/aggregate/Sum.java b/src/main/java/org/mybatis/dynamic/sql/select/aggregate/Sum.java index c499c9832..ac2636afd 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/aggregate/Sum.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/aggregate/Sum.java @@ -15,25 +15,27 @@ */ package org.mybatis.dynamic.sql.select.aggregate; -import org.mybatis.dynamic.sql.BasicColumn; +import org.mybatis.dynamic.sql.BindableColumn; +import org.mybatis.dynamic.sql.render.TableAliasCalculator; +import org.mybatis.dynamic.sql.select.function.AbstractUniTypeFunction; -public class Sum extends AbstractAggregate { +public class Sum extends AbstractUniTypeFunction> { - private Sum(BasicColumn column) { + private Sum(BindableColumn column) { super(column); } - + @Override - protected String render(String columnName) { - return "sum(" + columnName + ")"; //$NON-NLS-1$ //$NON-NLS-2$ + public String renderWithTableAlias(TableAliasCalculator tableAliasCalculator) { + return "sum(" + column.renderWithTableAlias(tableAliasCalculator) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ } @Override - protected Sum copy() { - return new Sum(column); + protected Sum copy() { + return new Sum<>(column); } - public static Sum of(BasicColumn column) { - return new Sum(column); + public static Sum of(BindableColumn column) { + return new Sum<>(column); } } diff --git a/src/test/java/examples/animal/data/AnimalDataTest.java b/src/test/java/examples/animal/data/AnimalDataTest.java index bbcd74e4a..3e074622b 100644 --- a/src/test/java/examples/animal/data/AnimalDataTest.java +++ b/src/test/java/examples/animal/data/AnimalDataTest.java @@ -1825,6 +1825,25 @@ void testAvg() { } } + @Test + void testDeprecatedAvg() { + try (SqlSession sqlSession = sqlSessionFactory.openSession()) { + GeneralMapper mapper = sqlSession.getMapper(GeneralMapper.class); + + SelectStatementProvider selectStatement = select(DeprecatedAverage.of(brainWeight).as("average")) + .from(animalData, "a") + .build() + .render(RenderingStrategies.MYBATIS3); + + Double average = mapper.selectOneDouble(selectStatement); + + assertAll( + () -> assertThat(selectStatement.getSelectStatement()).isEqualTo("select avg(a.brain_weight) as average from AnimalData a"), + () -> assertThat(average).isEqualTo(1852.69, within(.01)) + ); + } + } + @Test void testSum() { try (SqlSession sqlSession = sqlSessionFactory.openSession()) { diff --git a/src/test/java/examples/animal/data/DeprecatedAverage.java b/src/test/java/examples/animal/data/DeprecatedAverage.java new file mode 100644 index 000000000..f9487a8fc --- /dev/null +++ b/src/test/java/examples/animal/data/DeprecatedAverage.java @@ -0,0 +1,39 @@ +/* + * Copyright 2016-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package examples.animal.data; + +import org.mybatis.dynamic.sql.BasicColumn; +import org.mybatis.dynamic.sql.select.aggregate.AbstractAggregate; + +public class DeprecatedAverage extends AbstractAggregate { + private DeprecatedAverage(BasicColumn column) { + super(column); + } + + @Override + protected String render(String columnName) { + return "avg(" + columnName + ")"; //$NON-NLS-1$ //$NON-NLS-2$ + } + + @Override + protected DeprecatedAverage copy() { + return new DeprecatedAverage(column); + } + + public static DeprecatedAverage of(BasicColumn column) { + return new DeprecatedAverage(column); + } +} diff --git a/src/test/java/examples/array/NamesTableDynamicSqlSupport.java b/src/test/java/examples/array/NamesTableDynamicSqlSupport.java index 04deabd17..747a3645b 100644 --- a/src/test/java/examples/array/NamesTableDynamicSqlSupport.java +++ b/src/test/java/examples/array/NamesTableDynamicSqlSupport.java @@ -30,6 +30,7 @@ public NamesTable() { super("NamesTable"); } public final SqlColumn id = column("id", JDBCType.INTEGER); - public final SqlColumn names = column("names", JDBCType.ARRAY); + public final SqlColumn names = column("names", JDBCType.ARRAY, + "examples.array.StringArrayTypeHandler"); } } diff --git a/src/test/java/examples/array/StringArrayTypeHandler.java b/src/test/java/examples/array/StringArrayTypeHandler.java index db9a8e6b1..0b85fcc23 100644 --- a/src/test/java/examples/array/StringArrayTypeHandler.java +++ b/src/test/java/examples/array/StringArrayTypeHandler.java @@ -30,7 +30,7 @@ public class StringArrayTypeHandler extends BaseTypeHandler { @Override public void setNonNullParameter(PreparedStatement ps, int i, String[] parameter, JdbcType jdbcType) throws SQLException { - Array array = ps.getConnection().createArrayOf("CHAR", parameter); + Array array = ps.getConnection().createArrayOf("VARCHAR", parameter); ps.setArray(i, array); array.free(); }