From cd452ac502d55d082c267f5ea511628a929937ca Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Thu, 1 Aug 2024 11:04:22 -0400 Subject: [PATCH 1/9] Shim in a more general render method for sort specification --- .../dynamic/sql/SortSpecification.java | 29 +++++++++++++++++-- .../org/mybatis/dynamic/sql/SqlColumn.java | 23 ++++++--------- .../dynamic/sql/common/OrderByRenderer.java | 24 +++++++-------- .../sql/delete/render/DeleteRenderer.java | 2 +- .../sql/select/ColumnSortSpecification.java | 21 ++++++-------- .../sql/select/SimpleSortSpecification.java | 21 ++++++-------- .../select/render/MultiSelectRenderer.java | 2 +- .../sql/select/render/SelectRenderer.java | 2 +- .../sql/update/render/UpdateRenderer.java | 2 +- .../dynamic/sql/util/messages.properties | 4 ++- 10 files changed, 73 insertions(+), 57 deletions(-) diff --git a/src/main/java/org/mybatis/dynamic/sql/SortSpecification.java b/src/main/java/org/mybatis/dynamic/sql/SortSpecification.java index a17557017..85f9f5288 100644 --- a/src/main/java/org/mybatis/dynamic/sql/SortSpecification.java +++ b/src/main/java/org/mybatis/dynamic/sql/SortSpecification.java @@ -15,6 +15,11 @@ */ package org.mybatis.dynamic.sql; +import org.mybatis.dynamic.sql.exception.DynamicSqlException; +import org.mybatis.dynamic.sql.render.RenderingContext; +import org.mybatis.dynamic.sql.util.FragmentAndParameters; +import org.mybatis.dynamic.sql.util.Messages; + /** * Defines attributes of columns that are necessary for rendering an order by expression. * @@ -34,13 +39,33 @@ public interface SortSpecification { * NOT include the "DESC" word for descending sort specifications. * * @return the order by phrase + * @deprecated Please replace this method by overriding the more general "renderForOrderBy" method. Target for + * removal in release 2.1 */ - String orderByName(); + @Deprecated + default String orderByName() { + throw new DynamicSqlException(Messages.getString("ERROR.44")); //$NON-NLS-1$ + } /** * Return true if the sort order is descending. * * @return true if the SortSpecification should render as descending + * @deprecated Please replace this method by overriding the more general "renderForOrderBy" method. Target for + * removal in release 2.1 */ - boolean isDescending(); + @Deprecated + default boolean isDescending() { + throw new DynamicSqlException(Messages.getString("ERROR.44")); //$NON-NLS-1$ + } + + // the default implementation ensures compatibility with prior releases. When the + // deprecated methods are removed, this function can become purely abstract. + default FragmentAndParameters renderForOrderBy(RenderingContext renderingContext) { + String phrase = orderByName(); + if (isDescending()) { + phrase = phrase + " DESC"; //$NON-NLS-1$ + } + return FragmentAndParameters.fromFragment(phrase); + } } diff --git a/src/main/java/org/mybatis/dynamic/sql/SqlColumn.java b/src/main/java/org/mybatis/dynamic/sql/SqlColumn.java index 76f40e15c..0c8475d33 100644 --- a/src/main/java/org/mybatis/dynamic/sql/SqlColumn.java +++ b/src/main/java/org/mybatis/dynamic/sql/SqlColumn.java @@ -30,7 +30,7 @@ public class SqlColumn implements BindableColumn, SortSpecification { protected final String name; protected final SqlTable table; protected final JDBCType jdbcType; - protected final boolean isDescending; + protected final String descendingPhrase; protected final String alias; protected final String typeHandler; protected final RenderingStrategy renderingStrategy; @@ -42,7 +42,7 @@ private SqlColumn(Builder builder) { name = Objects.requireNonNull(builder.name); table = Objects.requireNonNull(builder.table); jdbcType = builder.jdbcType; - isDescending = builder.isDescending; + descendingPhrase = builder.descendingPhrase; alias = builder.alias; typeHandler = builder.typeHandler; renderingStrategy = builder.renderingStrategy; @@ -87,7 +87,7 @@ public Object convertParameterType(T value) { @Override public SortSpecification descending() { Builder b = copy(); - return b.withDescending(true).build(); + return b.withDescendingPhrase(" DESC").build(); //$NON-NLS-1$ } @Override @@ -126,13 +126,8 @@ public SqlColumn asCamelCase() { } @Override - public boolean isDescending() { - return isDescending; - } - - @Override - public String orderByName() { - return alias().orElse(name); + public FragmentAndParameters renderForOrderBy(RenderingContext renderingContext) { + return FragmentAndParameters.fromFragment(alias().orElse(name) + descendingPhrase); } @Override @@ -188,7 +183,7 @@ private Builder copy() { .withName(this.name) .withTable(this.table) .withJdbcType(this.jdbcType) - .withDescending(this.isDescending) + .withDescendingPhrase(this.descendingPhrase) .withAlias(this.alias) .withTypeHandler(this.typeHandler) .withRenderingStrategy(this.renderingStrategy) @@ -214,7 +209,7 @@ public static class Builder { protected String name; protected SqlTable table; protected JDBCType jdbcType; - protected boolean isDescending = false; + protected String descendingPhrase = ""; //$NON-NLS-1$ protected String alias; protected String typeHandler; protected RenderingStrategy renderingStrategy; @@ -237,8 +232,8 @@ public Builder withJdbcType(JDBCType jdbcType) { return this; } - public Builder withDescending(boolean isDescending) { - this.isDescending = isDescending; + public Builder withDescendingPhrase(String descendingPhrase) { + this.descendingPhrase = descendingPhrase; return this; } diff --git a/src/main/java/org/mybatis/dynamic/sql/common/OrderByRenderer.java b/src/main/java/org/mybatis/dynamic/sql/common/OrderByRenderer.java index f1a28ed4e..206c1a297 100644 --- a/src/main/java/org/mybatis/dynamic/sql/common/OrderByRenderer.java +++ b/src/main/java/org/mybatis/dynamic/sql/common/OrderByRenderer.java @@ -15,24 +15,24 @@ */ package org.mybatis.dynamic.sql.common; +import java.util.Objects; import java.util.stream.Collectors; -import org.mybatis.dynamic.sql.SortSpecification; +import org.mybatis.dynamic.sql.render.RenderingContext; import org.mybatis.dynamic.sql.util.FragmentAndParameters; +import org.mybatis.dynamic.sql.util.FragmentCollector; public class OrderByRenderer { - public FragmentAndParameters render(OrderByModel orderByModel) { - String phrase = orderByModel.columns() - .map(this::calculateOrderByPhrase) - .collect(Collectors.joining(", ", "order by ", "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - return FragmentAndParameters.fromFragment(phrase); + private final RenderingContext renderingContext; + + public OrderByRenderer(RenderingContext renderingContext) { + this.renderingContext = Objects.requireNonNull(renderingContext); } - private String calculateOrderByPhrase(SortSpecification column) { - String phrase = column.orderByName(); - if (column.isDescending()) { - phrase = phrase + " DESC"; //$NON-NLS-1$ - } - return phrase; + public FragmentAndParameters render(OrderByModel orderByModel) { + return orderByModel.columns().map(c -> c.renderForOrderBy(renderingContext)) + .collect(FragmentCollector.collect()) + .toFragmentAndParameters( + Collectors.joining(", ", "order by ", "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } } diff --git a/src/main/java/org/mybatis/dynamic/sql/delete/render/DeleteRenderer.java b/src/main/java/org/mybatis/dynamic/sql/delete/render/DeleteRenderer.java index ce46c4c10..8a9c945d4 100644 --- a/src/main/java/org/mybatis/dynamic/sql/delete/render/DeleteRenderer.java +++ b/src/main/java/org/mybatis/dynamic/sql/delete/render/DeleteRenderer.java @@ -96,7 +96,7 @@ private Optional calculateOrderByClause() { } private FragmentAndParameters renderOrderByClause(OrderByModel orderByModel) { - return new OrderByRenderer().render(orderByModel); + return new OrderByRenderer(renderingContext).render(orderByModel); } public static Builder withDeleteModel(DeleteModel deleteModel) { diff --git a/src/main/java/org/mybatis/dynamic/sql/select/ColumnSortSpecification.java b/src/main/java/org/mybatis/dynamic/sql/select/ColumnSortSpecification.java index b8503a971..4420affc9 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/ColumnSortSpecification.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/ColumnSortSpecification.java @@ -19,34 +19,31 @@ import org.mybatis.dynamic.sql.SortSpecification; import org.mybatis.dynamic.sql.SqlColumn; +import org.mybatis.dynamic.sql.render.RenderingContext; +import org.mybatis.dynamic.sql.util.FragmentAndParameters; public class ColumnSortSpecification implements SortSpecification { private final String tableAlias; private final SqlColumn column; - private final boolean isDescending; + private final String descendingPhrase; public ColumnSortSpecification(String tableAlias, SqlColumn column) { - this(tableAlias, column, false); + this(tableAlias, column, ""); //$NON-NLS-1$ } - private ColumnSortSpecification(String tableAlias, SqlColumn column, boolean isDescending) { + private ColumnSortSpecification(String tableAlias, SqlColumn column, String descendingPhrase) { this.tableAlias = Objects.requireNonNull(tableAlias); this.column = Objects.requireNonNull(column); - this.isDescending = isDescending; + this.descendingPhrase = descendingPhrase; } @Override public SortSpecification descending() { - return new ColumnSortSpecification(tableAlias, column, true); + return new ColumnSortSpecification(tableAlias, column, " DESC"); //$NON-NLS-1$ } @Override - public String orderByName() { - return tableAlias + "." + column.name(); //$NON-NLS-1$ - } - - @Override - public boolean isDescending() { - return isDescending; + public FragmentAndParameters renderForOrderBy(RenderingContext renderingContext) { + return FragmentAndParameters.fromFragment(tableAlias + "." + column.name() + descendingPhrase); //$NON-NLS-1$ } } diff --git a/src/main/java/org/mybatis/dynamic/sql/select/SimpleSortSpecification.java b/src/main/java/org/mybatis/dynamic/sql/select/SimpleSortSpecification.java index 9620020e2..2c363ccc4 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/SimpleSortSpecification.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/SimpleSortSpecification.java @@ -18,6 +18,8 @@ import java.util.Objects; import org.mybatis.dynamic.sql.SortSpecification; +import org.mybatis.dynamic.sql.render.RenderingContext; +import org.mybatis.dynamic.sql.util.FragmentAndParameters; /** * This class is used for an order by phrase where there is no suitable column name @@ -28,30 +30,25 @@ public class SimpleSortSpecification implements SortSpecification { private final String name; - private final boolean isDescending; + private final String descendingPhrase; private SimpleSortSpecification(String name) { - this(name, false); + this(name, ""); //$NON-NLS-1$ } - private SimpleSortSpecification(String name, boolean isDescending) { + private SimpleSortSpecification(String name, String descendingPhrase) { this.name = Objects.requireNonNull(name); - this.isDescending = isDescending; + this.descendingPhrase = descendingPhrase; } @Override public SortSpecification descending() { - return new SimpleSortSpecification(name, true); + return new SimpleSortSpecification(name, " DESC"); //$NON-NLS-1$ } @Override - public String orderByName() { - return name; - } - - @Override - public boolean isDescending() { - return isDescending; + public FragmentAndParameters renderForOrderBy(RenderingContext renderingContext) { + return FragmentAndParameters.fromFragment(name + descendingPhrase); } public static SimpleSortSpecification of(String name) { diff --git a/src/main/java/org/mybatis/dynamic/sql/select/render/MultiSelectRenderer.java b/src/main/java/org/mybatis/dynamic/sql/select/render/MultiSelectRenderer.java index 59e926f67..c063e7866 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/render/MultiSelectRenderer.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/render/MultiSelectRenderer.java @@ -87,7 +87,7 @@ private Optional renderOrderBy() { } private FragmentAndParameters renderOrderBy(OrderByModel orderByModel) { - return new OrderByRenderer().render(orderByModel); + return new OrderByRenderer(renderingContext).render(orderByModel); } private Optional renderPagingModel() { diff --git a/src/main/java/org/mybatis/dynamic/sql/select/render/SelectRenderer.java b/src/main/java/org/mybatis/dynamic/sql/select/render/SelectRenderer.java index 3f65a51e4..128ab3e8e 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/render/SelectRenderer.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/render/SelectRenderer.java @@ -68,7 +68,7 @@ private Optional renderOrderBy() { } private FragmentAndParameters renderOrderBy(OrderByModel orderByModel) { - return new OrderByRenderer().render(orderByModel); + return new OrderByRenderer(renderingContext).render(orderByModel); } private Optional renderPagingModel() { diff --git a/src/main/java/org/mybatis/dynamic/sql/update/render/UpdateRenderer.java b/src/main/java/org/mybatis/dynamic/sql/update/render/UpdateRenderer.java index 50397ee7f..3edfed684 100644 --- a/src/main/java/org/mybatis/dynamic/sql/update/render/UpdateRenderer.java +++ b/src/main/java/org/mybatis/dynamic/sql/update/render/UpdateRenderer.java @@ -122,7 +122,7 @@ private Optional calculateOrderByClause() { } private FragmentAndParameters renderOrderByClause(OrderByModel orderByModel) { - return new OrderByRenderer().render(orderByModel); + return new OrderByRenderer(renderingContext).render(orderByModel); } public static Builder withUpdateModel(UpdateModel updateModel) { diff --git a/src/main/resources/org/mybatis/dynamic/sql/util/messages.properties b/src/main/resources/org/mybatis/dynamic/sql/util/messages.properties index 9927dbeec..35d0a810c 100644 --- a/src/main/resources/org/mybatis/dynamic/sql/util/messages.properties +++ b/src/main/resources/org/mybatis/dynamic/sql/util/messages.properties @@ -52,7 +52,7 @@ ERROR.33=Calling "select" or "selectDistinct" more than once is not allowed. Add union or unionAll expression ERROR.34=You must specify "select" or "selectDistinct" before any other clauses in a multi-select statement ERROR.35=Multi-select statements must have at least one "union" or "union all" expression -ERROR.36=You must either implement the "render" or "renderWithTableAlias" method in a column or function +ERROR.36=You must either implement the "render" or "renderWithTableAlias" method in a column or function ERROR.37=The "{0}" function does not support conditions that fail to render ERROR.38=Bound values cannot be aliased ERROR.39=When clauses in case expressions must render @@ -60,4 +60,6 @@ ERROR.40=Case expressions must have at least one "when" clause ERROR.41=You cannot call "then" in a Kotlin case expression more than once ERROR.42=You cannot call `else` in a Kotlin case expression more than once ERROR.43=A Kotlin cast expression must have one, and only one, `as` element +ERROR.44=You must either implement the "renderForOrderBy" method or both "orderByName" and "isDescending" methods in a \ + sort specification INTERNAL.ERROR=Internal Error {0} From 2d85bb46a33b02f36a376e60e475bbe0ec6735dc Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Mon, 5 Aug 2024 10:53:15 -0400 Subject: [PATCH 2/9] Allow case statements in order by phrases --- .../caseexpression/SearchedCaseDSL.java | 4 +- .../caseexpression/SearchedCaseModel.java | 26 +- .../select/caseexpression/SimpleCaseDSL.java | 4 +- .../caseexpression/SimpleCaseModel.java | 28 +- .../sql/select/render/SimpleCaseRenderer.java | 4 +- .../render/ColumnAndConditionRenderer.java | 4 +- .../mariadb/NumbersDynamicSQLSupport.java | 36 ++ .../examples/mariadb/OrderByCaseTest.java | 358 ++++++++++++++++++ .../canonical/SpringKotlinSubQueryTest.kt | 4 +- .../resources/examples/mariadb/CreateDB.sql | 12 + 10 files changed, 470 insertions(+), 10 deletions(-) create mode 100644 src/test/java/examples/mariadb/NumbersDynamicSQLSupport.java create mode 100644 src/test/java/examples/mariadb/OrderByCaseTest.java diff --git a/src/main/java/org/mybatis/dynamic/sql/select/caseexpression/SearchedCaseDSL.java b/src/main/java/org/mybatis/dynamic/sql/select/caseexpression/SearchedCaseDSL.java index 674012d3c..360fc344d 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/caseexpression/SearchedCaseDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/caseexpression/SearchedCaseDSL.java @@ -71,7 +71,7 @@ public SearchedCaseEnder else_(BasicColumn column) { return new SearchedCaseEnder(); } - public BasicColumn end() { + public SearchedCaseModel end() { return new SearchedCaseModel.Builder() .withElseValue(elseValue) .withWhenConditions(whenConditions) @@ -100,7 +100,7 @@ protected WhenDSL getThis() { } public class SearchedCaseEnder { - public BasicColumn end() { + public SearchedCaseModel end() { return SearchedCaseDSL.this.end(); } } diff --git a/src/main/java/org/mybatis/dynamic/sql/select/caseexpression/SearchedCaseModel.java b/src/main/java/org/mybatis/dynamic/sql/select/caseexpression/SearchedCaseModel.java index 65d3f949f..15fd864f8 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/caseexpression/SearchedCaseModel.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/caseexpression/SearchedCaseModel.java @@ -21,20 +21,23 @@ import java.util.stream.Stream; import org.mybatis.dynamic.sql.BasicColumn; +import org.mybatis.dynamic.sql.SortSpecification; import org.mybatis.dynamic.sql.render.RenderingContext; import org.mybatis.dynamic.sql.select.render.SearchedCaseRenderer; import org.mybatis.dynamic.sql.util.FragmentAndParameters; import org.mybatis.dynamic.sql.util.Validator; -public class SearchedCaseModel implements BasicColumn { +public class SearchedCaseModel implements BasicColumn, SortSpecification { private final List whenConditions; private final BasicColumn elseValue; private final String alias; + private final String descendingPhrase; private SearchedCaseModel(Builder builder) { whenConditions = builder.whenConditions; alias = builder.alias; elseValue = builder.elseValue; + descendingPhrase = builder.descendingPhrase; Validator.assertNotEmpty(whenConditions, "ERROR.40"); //$NON-NLS-1$ } @@ -56,9 +59,24 @@ public SearchedCaseModel as(String alias) { return new Builder().withWhenConditions(whenConditions) .withElseValue(elseValue) .withAlias(alias) + .withDescendingPhrase(descendingPhrase) .build(); } + @Override + public SearchedCaseModel descending() { + return new Builder().withWhenConditions(whenConditions) + .withElseValue(elseValue) + .withAlias(alias) + .withDescendingPhrase(" DESC") //$NON-NLS-1$ + .build(); + } + + @Override + public FragmentAndParameters renderForOrderBy(RenderingContext renderingContext) { + return render(renderingContext).mapFragment(f -> f + descendingPhrase); + } + @Override public FragmentAndParameters render(RenderingContext renderingContext) { return new SearchedCaseRenderer(this, renderingContext).render(); @@ -68,6 +86,7 @@ public static class Builder { private final List whenConditions = new ArrayList<>(); private BasicColumn elseValue; private String alias; + private String descendingPhrase = ""; //$NON-NLS-1$ public Builder withWhenConditions(List whenConditions) { this.whenConditions.addAll(whenConditions); @@ -84,6 +103,11 @@ public Builder withAlias(String alias) { return this; } + public Builder withDescendingPhrase(String descendingPhrase) { + this.descendingPhrase = descendingPhrase; + return this; + } + public SearchedCaseModel build() { return new SearchedCaseModel(this); } diff --git a/src/main/java/org/mybatis/dynamic/sql/select/caseexpression/SimpleCaseDSL.java b/src/main/java/org/mybatis/dynamic/sql/select/caseexpression/SimpleCaseDSL.java index 83e46473a..6b3f41338 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/caseexpression/SimpleCaseDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/caseexpression/SimpleCaseDSL.java @@ -60,7 +60,7 @@ public SimpleCaseEnder else_(BasicColumn column) { return new SimpleCaseEnder(); } - public BasicColumn end() { + public SimpleCaseModel end() { return new SimpleCaseModel.Builder() .withColumn(column) .withWhenConditions(whenConditions) @@ -100,7 +100,7 @@ public SimpleCaseDSL then(BasicColumn column) { } public class SimpleCaseEnder { - public BasicColumn end() { + public SimpleCaseModel end() { return SimpleCaseDSL.this.end(); } } diff --git a/src/main/java/org/mybatis/dynamic/sql/select/caseexpression/SimpleCaseModel.java b/src/main/java/org/mybatis/dynamic/sql/select/caseexpression/SimpleCaseModel.java index 4b71407ae..3c649c3da 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/caseexpression/SimpleCaseModel.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/caseexpression/SimpleCaseModel.java @@ -23,22 +23,25 @@ import org.mybatis.dynamic.sql.BasicColumn; import org.mybatis.dynamic.sql.BindableColumn; +import org.mybatis.dynamic.sql.SortSpecification; import org.mybatis.dynamic.sql.render.RenderingContext; import org.mybatis.dynamic.sql.select.render.SimpleCaseRenderer; import org.mybatis.dynamic.sql.util.FragmentAndParameters; import org.mybatis.dynamic.sql.util.Validator; -public class SimpleCaseModel implements BasicColumn { +public class SimpleCaseModel implements BasicColumn, SortSpecification { private final BindableColumn column; private final List> whenConditions; private final BasicColumn elseValue; private final String alias; + private final String descendingPhrase; private SimpleCaseModel(Builder builder) { column = Objects.requireNonNull(builder.column); whenConditions = builder.whenConditions; elseValue = builder.elseValue; alias = builder.alias; + descendingPhrase = builder.descendingPhrase; Validator.assertNotEmpty(whenConditions, "ERROR.40"); //$NON-NLS-1$ } @@ -66,9 +69,26 @@ public SimpleCaseModel as(String alias) { .withWhenConditions(whenConditions) .withElseValue(elseValue) .withAlias(alias) + .withDescendingPhrase(descendingPhrase) .build(); } + @Override + public SimpleCaseModel descending() { + return new Builder() + .withColumn(column) + .withWhenConditions(whenConditions) + .withElseValue(elseValue) + .withAlias(alias) + .withDescendingPhrase(" DESC") //$NON-NLS-1$ + .build(); + } + + @Override + public FragmentAndParameters renderForOrderBy(RenderingContext renderingContext) { + return render(renderingContext).mapFragment(f -> f + descendingPhrase); + } + @Override public FragmentAndParameters render(RenderingContext renderingContext) { return new SimpleCaseRenderer<>(this, renderingContext).render(); @@ -79,6 +99,7 @@ public static class Builder { private final List> whenConditions = new ArrayList<>(); private BasicColumn elseValue; private String alias; + private String descendingPhrase = ""; //$NON-NLS-1$ public Builder withColumn(BindableColumn column) { this.column = column; @@ -100,6 +121,11 @@ public Builder withAlias(String alias) { return this; } + public Builder withDescendingPhrase(String descendingPhrase) { + this.descendingPhrase = descendingPhrase; + return this; + } + public SimpleCaseModel build() { return new SimpleCaseModel<>(this); } diff --git a/src/main/java/org/mybatis/dynamic/sql/select/render/SimpleCaseRenderer.java b/src/main/java/org/mybatis/dynamic/sql/select/render/SimpleCaseRenderer.java index 2639d0b53..94cd071f1 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/render/SimpleCaseRenderer.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/render/SimpleCaseRenderer.java @@ -48,7 +48,9 @@ public FragmentAndParameters render() { } private FragmentAndParameters renderCase() { - return simpleCaseModel.column().render(renderingContext) + return simpleCaseModel.column().alias() + .map(FragmentAndParameters::fromFragment) + .orElseGet(() -> simpleCaseModel.column().render(renderingContext)) .mapFragment(f -> "case " + f); //$NON-NLS-1$ } diff --git a/src/main/java/org/mybatis/dynamic/sql/where/render/ColumnAndConditionRenderer.java b/src/main/java/org/mybatis/dynamic/sql/where/render/ColumnAndConditionRenderer.java index 2a78ccbf8..da1050ed8 100644 --- a/src/main/java/org/mybatis/dynamic/sql/where/render/ColumnAndConditionRenderer.java +++ b/src/main/java/org/mybatis/dynamic/sql/where/render/ColumnAndConditionRenderer.java @@ -36,7 +36,9 @@ private ColumnAndConditionRenderer(Builder builder) { } public FragmentAndParameters render() { - FragmentAndParameters renderedLeftColumn = column.render(renderingContext); + FragmentAndParameters renderedLeftColumn = column.alias() + .map(FragmentAndParameters::fromFragment) + .orElseGet(() -> column.render(renderingContext)); DefaultConditionVisitor visitor = DefaultConditionVisitor.withColumn(column) .withRenderingContext(renderingContext) diff --git a/src/test/java/examples/mariadb/NumbersDynamicSQLSupport.java b/src/test/java/examples/mariadb/NumbersDynamicSQLSupport.java new file mode 100644 index 000000000..f707b91fe --- /dev/null +++ b/src/test/java/examples/mariadb/NumbersDynamicSQLSupport.java @@ -0,0 +1,36 @@ +/* + * Copyright 2016-2024 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 + * + * https://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.mariadb; + +import org.mybatis.dynamic.sql.SqlColumn; +import org.mybatis.dynamic.sql.SqlTable; + +import java.sql.JDBCType; + +public final class NumbersDynamicSQLSupport { + public static final Numbers numbers = new Numbers(); + public static final SqlColumn id = numbers.id; + public static final SqlColumn description = numbers.description; + + public static final class Numbers extends SqlTable { + public final SqlColumn id = column("id", JDBCType.INTEGER); + public final SqlColumn description = column("description", JDBCType.VARCHAR); + + public Numbers() { + super("numbers"); + } + } +} diff --git a/src/test/java/examples/mariadb/OrderByCaseTest.java b/src/test/java/examples/mariadb/OrderByCaseTest.java new file mode 100644 index 000000000..0e0daf251 --- /dev/null +++ b/src/test/java/examples/mariadb/OrderByCaseTest.java @@ -0,0 +1,358 @@ +/* + * Copyright 2016-2024 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 + * + * https://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.mariadb; + +import static examples.mariadb.NumbersDynamicSQLSupport.description; +import static examples.mariadb.NumbersDynamicSQLSupport.id; +import static examples.mariadb.NumbersDynamicSQLSupport.numbers; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mybatis.dynamic.sql.SqlBuilder.case_; +import static org.mybatis.dynamic.sql.SqlBuilder.isEqualTo; +import static org.mybatis.dynamic.sql.SqlBuilder.select; + +import java.util.List; +import java.util.Map; + +import config.TestContainersConfiguration; +import org.apache.ibatis.datasource.unpooled.UnpooledDataSource; +import org.apache.ibatis.mapping.Environment; +import org.apache.ibatis.session.Configuration; +import org.apache.ibatis.session.SqlSession; +import org.apache.ibatis.session.SqlSessionFactory; +import org.apache.ibatis.session.SqlSessionFactoryBuilder; +import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.mybatis.dynamic.sql.render.RenderingStrategies; +import org.mybatis.dynamic.sql.select.render.SelectStatementProvider; +import org.mybatis.dynamic.sql.util.mybatis3.CommonSelectMapper; +import org.testcontainers.containers.MariaDBContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +@Testcontainers +class OrderByCaseTest { + + @SuppressWarnings("resource") + @Container + private static final MariaDBContainer mariadb = + new MariaDBContainer<>(TestContainersConfiguration.MARIADB_LATEST) + .withInitScript("examples/mariadb/CreateDB.sql"); + + private static SqlSessionFactory sqlSessionFactory; + + @BeforeAll + static void setup() { + UnpooledDataSource ds = new UnpooledDataSource(mariadb.getDriverClassName(), mariadb.getJdbcUrl(), + mariadb.getUsername(), mariadb.getPassword()); + Environment environment = new Environment("test", new JdbcTransactionFactory(), ds); + Configuration config = new Configuration(environment); + config.addMapper(CommonSelectMapper.class); + sqlSessionFactory = new SqlSessionFactoryBuilder().build(config); + } + + @Test + void testOrderBySimpleCase() { + try (SqlSession session = sqlSessionFactory.openSession()) { + CommonSelectMapper mapper = session.getMapper(CommonSelectMapper.class); + + SelectStatementProvider selectStatement = select(id, description).from(numbers) + .orderBy(case_(description) + .when("One").then(3) + .when("Two").then(5) + .when("Three").then(4) + .when("Four").then(2) + .when("Five").then(1) + .else_(99) + .end()) + .build() + .render(RenderingStrategies.MYBATIS3); + + String expected = "select id, description from numbers order by case description " + + "when #{parameters.p1,jdbcType=VARCHAR} then 3 " + + "when #{parameters.p2,jdbcType=VARCHAR} then 5 " + + "when #{parameters.p3,jdbcType=VARCHAR} then 4 " + + "when #{parameters.p4,jdbcType=VARCHAR} then 2 " + + "when #{parameters.p5,jdbcType=VARCHAR} then 1 else 99 end"; + + assertThat(selectStatement.getSelectStatement()).isEqualTo( expected); + + List> rows = mapper.selectManyMappedRows(selectStatement); + assertThat(rows).hasSize(5); + assertThat(rows.get(0)).extracting("id", "description").containsExactly(5, "Five"); + assertThat(rows.get(1)).extracting("id", "description").containsExactly(4, "Four"); + assertThat(rows.get(2)).extracting("id", "description").containsExactly(1, "One"); + assertThat(rows.get(3)).extracting("id", "description").containsExactly(3, "Three"); + assertThat(rows.get(4)).extracting("id", "description").containsExactly(2, "Two"); + } + } + + @Test + void testOrderBySimpleCaseWithTableAlias() { + // ignore table aliases in order by phrases + try (SqlSession session = sqlSessionFactory.openSession()) { + CommonSelectMapper mapper = session.getMapper(CommonSelectMapper.class); + + SelectStatementProvider selectStatement = select(id, description).from(numbers, "n") + .orderBy(case_(description) + .when("One").then(3) + .when("Two").then(5) + .when("Three").then(4) + .when("Four").then(2) + .when("Five").then(1) + .else_(99) + .end()) + .build() + .render(RenderingStrategies.MYBATIS3); + + String expected = "select n.id, n.description from numbers n order by case description " + + "when #{parameters.p1,jdbcType=VARCHAR} then 3 " + + "when #{parameters.p2,jdbcType=VARCHAR} then 5 " + + "when #{parameters.p3,jdbcType=VARCHAR} then 4 " + + "when #{parameters.p4,jdbcType=VARCHAR} then 2 " + + "when #{parameters.p5,jdbcType=VARCHAR} then 1 else 99 end"; + + assertThat(selectStatement.getSelectStatement()).isEqualTo( expected); + + List> rows = mapper.selectManyMappedRows(selectStatement); + assertThat(rows).hasSize(5); + assertThat(rows.get(0)).extracting("id", "description").containsExactly(5, "Five"); + assertThat(rows.get(1)).extracting("id", "description").containsExactly(4, "Four"); + assertThat(rows.get(2)).extracting("id", "description").containsExactly(1, "One"); + assertThat(rows.get(3)).extracting("id", "description").containsExactly(3, "Three"); + assertThat(rows.get(4)).extracting("id", "description").containsExactly(2, "Two"); + } + } + + @Test + void testOrderBySimpleCaseWithColumnAlias() { + // ignore table aliases in order by phrases + try (SqlSession session = sqlSessionFactory.openSession()) { + CommonSelectMapper mapper = session.getMapper(CommonSelectMapper.class); + + SelectStatementProvider selectStatement = select(id, description.as("descr")).from(numbers) + .orderBy(case_(description.as("descr")) + .when("One").then(3) + .when("Two").then(5) + .when("Three").then(4) + .when("Four").then(2) + .when("Five").then(1) + .else_(99) + .end()) + .build() + .render(RenderingStrategies.MYBATIS3); + + String expected = "select id, description as descr from numbers order by case descr " + + "when #{parameters.p1,jdbcType=VARCHAR} then 3 " + + "when #{parameters.p2,jdbcType=VARCHAR} then 5 " + + "when #{parameters.p3,jdbcType=VARCHAR} then 4 " + + "when #{parameters.p4,jdbcType=VARCHAR} then 2 " + + "when #{parameters.p5,jdbcType=VARCHAR} then 1 else 99 end"; + + assertThat(selectStatement.getSelectStatement()).isEqualTo( expected); + + List> rows = mapper.selectManyMappedRows(selectStatement); + assertThat(rows).hasSize(5); + assertThat(rows.get(0)).extracting("id", "descr").containsExactly(5, "Five"); + assertThat(rows.get(1)).extracting("id", "descr").containsExactly(4, "Four"); + assertThat(rows.get(2)).extracting("id", "descr").containsExactly(1, "One"); + assertThat(rows.get(3)).extracting("id", "descr").containsExactly(3, "Three"); + assertThat(rows.get(4)).extracting("id", "descr").containsExactly(2, "Two"); + } + } + + @Test + void testOrderBySimpleCaseDescending() { + try (SqlSession session = sqlSessionFactory.openSession()) { + CommonSelectMapper mapper = session.getMapper(CommonSelectMapper.class); + + SelectStatementProvider selectStatement = select(id, description).from(numbers) + .orderBy(case_(description) + .when("One").then(3) + .when("Two").then(5) + .when("Three").then(4) + .when("Four").then(2) + .when("Five").then(1) + .else_(99) + .end().descending()) + .build() + .render(RenderingStrategies.MYBATIS3); + + String expected = "select id, description from numbers order by case description " + + "when #{parameters.p1,jdbcType=VARCHAR} then 3 " + + "when #{parameters.p2,jdbcType=VARCHAR} then 5 " + + "when #{parameters.p3,jdbcType=VARCHAR} then 4 " + + "when #{parameters.p4,jdbcType=VARCHAR} then 2 " + + "when #{parameters.p5,jdbcType=VARCHAR} then 1 else 99 end DESC"; + + assertThat(selectStatement.getSelectStatement()).isEqualTo( expected); + + List> rows = mapper.selectManyMappedRows(selectStatement); + assertThat(rows).hasSize(5); + assertThat(rows.get(4)).extracting("id", "description").containsExactly(5, "Five"); + assertThat(rows.get(3)).extracting("id", "description").containsExactly(4, "Four"); + assertThat(rows.get(2)).extracting("id", "description").containsExactly(1, "One"); + assertThat(rows.get(1)).extracting("id", "description").containsExactly(3, "Three"); + assertThat(rows.get(0)).extracting("id", "description").containsExactly(2, "Two"); + } + } + + @Test + void testOrderBySearchedCase() { + try (SqlSession session = sqlSessionFactory.openSession()) { + CommonSelectMapper mapper = session.getMapper(CommonSelectMapper.class); + + SelectStatementProvider selectStatement = select(id, description).from(numbers) + .orderBy(case_() + .when(description, isEqualTo("One")).then(3) + .when(description, isEqualTo("Two")).then(5) + .when(description, isEqualTo("Three")).then(4) + .when(description, isEqualTo("Four")).then(2) + .when(description, isEqualTo("Five")).then(1) + .else_(99) + .end()) + .build() + .render(RenderingStrategies.MYBATIS3); + + String expected = "select id, description from numbers order by case " + + "when description = #{parameters.p1,jdbcType=VARCHAR} then 3 " + + "when description = #{parameters.p2,jdbcType=VARCHAR} then 5 " + + "when description = #{parameters.p3,jdbcType=VARCHAR} then 4 " + + "when description = #{parameters.p4,jdbcType=VARCHAR} then 2 " + + "when description = #{parameters.p5,jdbcType=VARCHAR} then 1 else 99 end"; + + assertThat(selectStatement.getSelectStatement()).isEqualTo( expected); + + List> rows = mapper.selectManyMappedRows(selectStatement); + assertThat(rows).hasSize(5); + assertThat(rows.get(0)).extracting("id", "description").containsExactly(5, "Five"); + assertThat(rows.get(1)).extracting("id", "description").containsExactly(4, "Four"); + assertThat(rows.get(2)).extracting("id", "description").containsExactly(1, "One"); + assertThat(rows.get(3)).extracting("id", "description").containsExactly(3, "Three"); + assertThat(rows.get(4)).extracting("id", "description").containsExactly(2, "Two"); + } + } + + @Test + void testOrderBySearchedCaseWithTableAlias() { + // ignore table aliases in order by phrases + try (SqlSession session = sqlSessionFactory.openSession()) { + CommonSelectMapper mapper = session.getMapper(CommonSelectMapper.class); + + SelectStatementProvider selectStatement = select(id, description).from(numbers, "n") + .orderBy(case_() + .when(description, isEqualTo("One")).then(3) + .when(description, isEqualTo("Two")).then(5) + .when(description, isEqualTo("Three")).then(4) + .when(description, isEqualTo("Four")).then(2) + .when(description, isEqualTo("Five")).then(1) + .else_(99) + .end()) + .build() + .render(RenderingStrategies.MYBATIS3); + + String expected = "select n.id, n.description from numbers n order by case " + + "when description = #{parameters.p1,jdbcType=VARCHAR} then 3 " + + "when description = #{parameters.p2,jdbcType=VARCHAR} then 5 " + + "when description = #{parameters.p3,jdbcType=VARCHAR} then 4 " + + "when description = #{parameters.p4,jdbcType=VARCHAR} then 2 " + + "when description = #{parameters.p5,jdbcType=VARCHAR} then 1 else 99 end"; + + assertThat(selectStatement.getSelectStatement()).isEqualTo( expected); + + List> rows = mapper.selectManyMappedRows(selectStatement); + assertThat(rows).hasSize(5); + assertThat(rows.get(0)).extracting("id", "description").containsExactly(5, "Five"); + assertThat(rows.get(1)).extracting("id", "description").containsExactly(4, "Four"); + assertThat(rows.get(2)).extracting("id", "description").containsExactly(1, "One"); + assertThat(rows.get(3)).extracting("id", "description").containsExactly(3, "Three"); + assertThat(rows.get(4)).extracting("id", "description").containsExactly(2, "Two"); + } + } + + @Test + void testOrderBySearchedCaseWithColumnAlias() { + // ignore table aliases in order by phrases + try (SqlSession session = sqlSessionFactory.openSession()) { + CommonSelectMapper mapper = session.getMapper(CommonSelectMapper.class); + + SelectStatementProvider selectStatement = select(id, description.as("descr")).from(numbers) + .orderBy(case_() + .when(description.as("descr"), isEqualTo("One")).then(3) + .when(description.as("descr"), isEqualTo("Two")).then(5) + .when(description.as("descr"), isEqualTo("Three")).then(4) + .when(description.as("descr"), isEqualTo("Four")).then(2) + .when(description.as("descr"), isEqualTo("Five")).then(1) + .else_(99) + .end()) + .build() + .render(RenderingStrategies.MYBATIS3); + + String expected = "select id, description as descr from numbers order by case " + + "when descr = #{parameters.p1,jdbcType=VARCHAR} then 3 " + + "when descr = #{parameters.p2,jdbcType=VARCHAR} then 5 " + + "when descr = #{parameters.p3,jdbcType=VARCHAR} then 4 " + + "when descr = #{parameters.p4,jdbcType=VARCHAR} then 2 " + + "when descr = #{parameters.p5,jdbcType=VARCHAR} then 1 else 99 end"; + + assertThat(selectStatement.getSelectStatement()).isEqualTo( expected); + + List> rows = mapper.selectManyMappedRows(selectStatement); + assertThat(rows).hasSize(5); + assertThat(rows.get(0)).extracting("id", "descr").containsExactly(5, "Five"); + assertThat(rows.get(1)).extracting("id", "descr").containsExactly(4, "Four"); + assertThat(rows.get(2)).extracting("id", "descr").containsExactly(1, "One"); + assertThat(rows.get(3)).extracting("id", "descr").containsExactly(3, "Three"); + assertThat(rows.get(4)).extracting("id", "descr").containsExactly(2, "Two"); + } + } + + @Test + void testOrderBySearchedCaseDescending() { + try (SqlSession session = sqlSessionFactory.openSession()) { + CommonSelectMapper mapper = session.getMapper(CommonSelectMapper.class); + + SelectStatementProvider selectStatement = select(id, description).from(numbers) + .orderBy(case_() + .when(description, isEqualTo("One")).then(3) + .when(description, isEqualTo("Two")).then(5) + .when(description, isEqualTo("Three")).then(4) + .when(description, isEqualTo("Four")).then(2) + .when(description, isEqualTo("Five")).then(1) + .else_(99) + .end().descending()) + .build() + .render(RenderingStrategies.MYBATIS3); + + String expected = "select id, description from numbers order by case " + + "when description = #{parameters.p1,jdbcType=VARCHAR} then 3 " + + "when description = #{parameters.p2,jdbcType=VARCHAR} then 5 " + + "when description = #{parameters.p3,jdbcType=VARCHAR} then 4 " + + "when description = #{parameters.p4,jdbcType=VARCHAR} then 2 " + + "when description = #{parameters.p5,jdbcType=VARCHAR} then 1 else 99 end DESC"; + + assertThat(selectStatement.getSelectStatement()).isEqualTo( expected); + + List> rows = mapper.selectManyMappedRows(selectStatement); + assertThat(rows).hasSize(5); + assertThat(rows.get(4)).extracting("id", "description").containsExactly(5, "Five"); + assertThat(rows.get(3)).extracting("id", "description").containsExactly(4, "Four"); + assertThat(rows.get(2)).extracting("id", "description").containsExactly(1, "One"); + assertThat(rows.get(1)).extracting("id", "description").containsExactly(3, "Three"); + assertThat(rows.get(0)).extracting("id", "description").containsExactly(2, "Two"); + } + } +} diff --git a/src/test/kotlin/examples/kotlin/spring/canonical/SpringKotlinSubQueryTest.kt b/src/test/kotlin/examples/kotlin/spring/canonical/SpringKotlinSubQueryTest.kt index eb97249a6..d4ff965b9 100644 --- a/src/test/kotlin/examples/kotlin/spring/canonical/SpringKotlinSubQueryTest.kt +++ b/src/test/kotlin/examples/kotlin/spring/canonical/SpringKotlinSubQueryTest.kt @@ -113,12 +113,12 @@ open class SpringKotlinSubQueryTest { @Test fun testBasicSubQueryWithAliases() { - val rowNum = DerivedColumn.of("rownum()") `as` "myRows" + val rowNum = DerivedColumn.of("rownum()") val outerFirstName = "b"(firstName) val personId = DerivedColumn.of("personId", "b") val selectStatement = - select(outerFirstName.asCamelCase(), personId, rowNum) { + select(outerFirstName.asCamelCase(), personId, rowNum `as` "myRows") { from { select(id `as` "personId", firstName) { from(person, "a") diff --git a/src/test/resources/examples/mariadb/CreateDB.sql b/src/test/resources/examples/mariadb/CreateDB.sql index 3e16f6a73..3c90c396d 100644 --- a/src/test/resources/examples/mariadb/CreateDB.sql +++ b/src/test/resources/examples/mariadb/CreateDB.sql @@ -41,3 +41,15 @@ insert into items values (17, 'Item 17', 117); insert into items values (18, 'Item 18', 118); insert into items values (19, 'Item 19', 119); insert into items values (20, 'Item 20', 120); + +create table numbers ( + id int not null, + description varchar(50) not null, + primary key (id) +); + +insert into numbers values (1, 'One'); +insert into numbers values (2, 'Two'); +insert into numbers values (3, 'Three'); +insert into numbers values (4, 'Four'); +insert into numbers values (5, 'Five'); From 6f483d823a5970d589840e0843dc0dd5b91558c5 Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Mon, 5 Aug 2024 17:04:34 -0400 Subject: [PATCH 3/9] Coverage for deprecated methods --- .../sql/DeprecatedSortMethodsTest.java | 142 ++++++++++++++++++ .../mybatis/dynamic/sql/InvalidSQLTest.java | 1 - 2 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 src/test/java/org/mybatis/dynamic/sql/DeprecatedSortMethodsTest.java diff --git a/src/test/java/org/mybatis/dynamic/sql/DeprecatedSortMethodsTest.java b/src/test/java/org/mybatis/dynamic/sql/DeprecatedSortMethodsTest.java new file mode 100644 index 000000000..678d997d2 --- /dev/null +++ b/src/test/java/org/mybatis/dynamic/sql/DeprecatedSortMethodsTest.java @@ -0,0 +1,142 @@ +/* + * Copyright 2016-2024 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 + * + * https://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; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +import java.util.List; + +import org.junit.jupiter.api.Test; +import org.mybatis.dynamic.sql.common.OrderByModel; +import org.mybatis.dynamic.sql.common.OrderByRenderer; +import org.mybatis.dynamic.sql.configuration.StatementConfiguration; +import org.mybatis.dynamic.sql.exception.DynamicSqlException; +import org.mybatis.dynamic.sql.render.RenderingContext; +import org.mybatis.dynamic.sql.render.RenderingStrategies; +import org.mybatis.dynamic.sql.render.TableAliasCalculator; +import org.mybatis.dynamic.sql.util.FragmentAndParameters; +import org.mybatis.dynamic.sql.util.Messages; + +class DeprecatedSortMethodsTest { + + @Test + void bothMethodsExist() { + SortSpecification ss = new SortSpecification() { + @Override + public SortSpecification descending() { + return this; + } + + @Override + public String orderByName() { + return "id"; + } + + @Override + public boolean isDescending() { + return true; + } + }; + + OrderByModel model = OrderByModel.of(List.of(ss)); + + RenderingContext renderingContext = RenderingContext + .withRenderingStrategy(RenderingStrategies.MYBATIS3) + .withTableAliasCalculator(TableAliasCalculator.empty()) + .withStatementConfiguration(new StatementConfiguration()) + .build(); + OrderByRenderer renderer = new OrderByRenderer(renderingContext); + FragmentAndParameters fp = renderer.render(model); + assertThat(fp.fragment()).isEqualTo("order by id DESC"); + } + + @Test + void orderByNameMethodMissing() { + SortSpecification ss = new SortSpecification() { + @Override + public SortSpecification descending() { + return this; + } + + @Override + public boolean isDescending() { + return true; + } + }; + + OrderByModel model = OrderByModel.of(List.of(ss)); + + RenderingContext renderingContext = RenderingContext + .withRenderingStrategy(RenderingStrategies.MYBATIS3) + .withTableAliasCalculator(TableAliasCalculator.empty()) + .withStatementConfiguration(new StatementConfiguration()) + .build(); + OrderByRenderer renderer = new OrderByRenderer(renderingContext); + assertThatExceptionOfType(DynamicSqlException.class) + .isThrownBy(() -> renderer.render(model)) + .withMessage(Messages.getString("ERROR.44")); + } + + @Test + void isDescendingMethodMissing() { + SortSpecification ss = new SortSpecification() { + @Override + public SortSpecification descending() { + return this; + } + + @Override + public String orderByName() { + return "id"; + } + }; + + OrderByModel model = OrderByModel.of(List.of(ss)); + + RenderingContext renderingContext = RenderingContext + .withRenderingStrategy(RenderingStrategies.MYBATIS3) + .withTableAliasCalculator(TableAliasCalculator.empty()) + .withStatementConfiguration(new StatementConfiguration()) + .build(); + OrderByRenderer renderer = new OrderByRenderer(renderingContext); + assertThatExceptionOfType(DynamicSqlException.class) + .isThrownBy(() -> renderer.render(model)) + .withMessage(Messages.getString("ERROR.44")); + } + + @Test + void bothMethodsMissing() { + SortSpecification ss = new SortSpecification() { + @Override + public SortSpecification descending() { + return this; + } + }; + + OrderByModel model = OrderByModel.of(List.of(ss)); + + RenderingContext renderingContext = RenderingContext + .withRenderingStrategy(RenderingStrategies.MYBATIS3) + .withTableAliasCalculator(TableAliasCalculator.empty()) + .withStatementConfiguration(new StatementConfiguration()) + .build(); + OrderByRenderer renderer = new OrderByRenderer(renderingContext); + assertThatExceptionOfType(DynamicSqlException.class) + .isThrownBy(() -> renderer.render(model)) + .withMessage(Messages.getString("ERROR.44")); + } +} diff --git a/src/test/java/org/mybatis/dynamic/sql/InvalidSQLTest.java b/src/test/java/org/mybatis/dynamic/sql/InvalidSQLTest.java index bfec86e73..cc5f16193 100644 --- a/src/test/java/org/mybatis/dynamic/sql/InvalidSQLTest.java +++ b/src/test/java/org/mybatis/dynamic/sql/InvalidSQLTest.java @@ -22,7 +22,6 @@ import static org.mybatis.dynamic.sql.SqlBuilder.update; import static org.mybatis.dynamic.sql.SqlBuilder.value; -import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.MissingResourceException; From d69b968dbea48b25978592de12a8bf26fc5abdb5 Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Tue, 6 Aug 2024 11:01:23 -0400 Subject: [PATCH 4/9] Sonar suggestions --- .../org/mybatis/dynamic/sql/AbstractListValueCondition.java | 2 +- src/main/java/org/mybatis/dynamic/sql/SortSpecification.java | 4 ++-- .../org/mybatis/dynamic/sql/insert/render/BatchInsert.java | 3 +-- .../dynamic/sql/select/AbstractQueryExpressionDSL.java | 3 +-- src/main/java/org/mybatis/dynamic/sql/select/SelectDSL.java | 3 +-- .../org/mybatis/dynamic/sql/update/render/UpdateRenderer.java | 4 ++-- .../java/org/mybatis/dynamic/sql/util/SqlProviderAdapter.java | 3 +-- .../mybatis/dynamic/sql/util/mybatis3/CommonSelectMapper.java | 3 +-- .../mybatis/dynamic/sql/util/spring/BatchInsertUtility.java | 3 +-- .../sql/where/condition/IsInCaseInsensitiveWhenPresent.java | 3 +-- .../mybatis/dynamic/sql/where/condition/IsInWhenPresent.java | 3 +-- .../where/condition/IsNotInCaseInsensitiveWhenPresent.java | 3 +-- .../dynamic/sql/where/condition/IsNotInWhenPresent.java | 3 +-- .../mybatis/dynamic/sql/where/render/CriterionRenderer.java | 2 +- 14 files changed, 16 insertions(+), 26 deletions(-) diff --git a/src/main/java/org/mybatis/dynamic/sql/AbstractListValueCondition.java b/src/main/java/org/mybatis/dynamic/sql/AbstractListValueCondition.java index 104859de8..dc287e842 100644 --- a/src/main/java/org/mybatis/dynamic/sql/AbstractListValueCondition.java +++ b/src/main/java/org/mybatis/dynamic/sql/AbstractListValueCondition.java @@ -51,7 +51,7 @@ private Collection applyMapper(Function mapper) { private Collection applyFilter(Predicate predicate) { Objects.requireNonNull(predicate); - return values.stream().filter(predicate).collect(Collectors.toList()); + return values.stream().filter(predicate).toList(); } protected > S filterSupport(Predicate predicate, diff --git a/src/main/java/org/mybatis/dynamic/sql/SortSpecification.java b/src/main/java/org/mybatis/dynamic/sql/SortSpecification.java index 85f9f5288..87b986d27 100644 --- a/src/main/java/org/mybatis/dynamic/sql/SortSpecification.java +++ b/src/main/java/org/mybatis/dynamic/sql/SortSpecification.java @@ -42,7 +42,7 @@ public interface SortSpecification { * @deprecated Please replace this method by overriding the more general "renderForOrderBy" method. Target for * removal in release 2.1 */ - @Deprecated + @Deprecated(since = "2.0", forRemoval = true) default String orderByName() { throw new DynamicSqlException(Messages.getString("ERROR.44")); //$NON-NLS-1$ } @@ -54,7 +54,7 @@ default String orderByName() { * @deprecated Please replace this method by overriding the more general "renderForOrderBy" method. Target for * removal in release 2.1 */ - @Deprecated + @Deprecated(since = "2.0", forRemoval = true) default boolean isDescending() { throw new DynamicSqlException(Messages.getString("ERROR.44")); //$NON-NLS-1$ } diff --git a/src/main/java/org/mybatis/dynamic/sql/insert/render/BatchInsert.java b/src/main/java/org/mybatis/dynamic/sql/insert/render/BatchInsert.java index 2759bb907..cde4ec626 100644 --- a/src/main/java/org/mybatis/dynamic/sql/insert/render/BatchInsert.java +++ b/src/main/java/org/mybatis/dynamic/sql/insert/render/BatchInsert.java @@ -19,7 +19,6 @@ import java.util.Collections; import java.util.List; import java.util.Objects; -import java.util.stream.Collectors; public class BatchInsert { private final String insertStatement; @@ -38,7 +37,7 @@ private BatchInsert(Builder builder) { public List> insertStatements() { return records.stream() .map(this::toInsertStatement) - .collect(Collectors.toList()); + .toList(); } private InsertStatementProvider toInsertStatement(T row) { diff --git a/src/main/java/org/mybatis/dynamic/sql/select/AbstractQueryExpressionDSL.java b/src/main/java/org/mybatis/dynamic/sql/select/AbstractQueryExpressionDSL.java index d800a02ff..d82076a49 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/AbstractQueryExpressionDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/AbstractQueryExpressionDSL.java @@ -23,7 +23,6 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; -import java.util.stream.Collectors; import org.mybatis.dynamic.sql.SqlTable; import org.mybatis.dynamic.sql.TableExpression; @@ -196,7 +195,7 @@ protected Optional buildJoinModel() { return Optional.of(JoinModel.of(joinSpecificationBuilders.stream() .map(JoinSpecification.Builder::build) - .collect(Collectors.toList()))); + .toList())); } protected void addTableAlias(SqlTable table, String tableAlias) { diff --git a/src/main/java/org/mybatis/dynamic/sql/select/SelectDSL.java b/src/main/java/org/mybatis/dynamic/sql/select/SelectDSL.java index a509e974b..cb1fae92d 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/SelectDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/SelectDSL.java @@ -23,7 +23,6 @@ import java.util.Optional; import java.util.function.Consumer; import java.util.function.Function; -import java.util.stream.Collectors; import org.jetbrains.annotations.NotNull; import org.mybatis.dynamic.sql.BasicColumn; @@ -143,7 +142,7 @@ public R build() { private List buildModels() { return queryExpressions.stream() .map(QueryExpressionDSL::buildModel) - .collect(Collectors.toList()); + .toList(); } private Optional buildPagingModel() { diff --git a/src/main/java/org/mybatis/dynamic/sql/update/render/UpdateRenderer.java b/src/main/java/org/mybatis/dynamic/sql/update/render/UpdateRenderer.java index 0a3fae0d1..f11662c02 100644 --- a/src/main/java/org/mybatis/dynamic/sql/update/render/UpdateRenderer.java +++ b/src/main/java/org/mybatis/dynamic/sql/update/render/UpdateRenderer.java @@ -78,8 +78,8 @@ private FragmentAndParameters calculateUpdateStatementStart() { private FragmentAndParameters calculateSetPhrase() { List> fragmentsAndParameters = updateModel.columnMappings() - .map(m -> m.accept(visitor)) - .collect(Collectors.toList()); + .map(m -> m.accept(visitor)) + .toList(); Validator.assertFalse(fragmentsAndParameters.stream().noneMatch(Optional::isPresent), "ERROR.18"); //$NON-NLS-1$ diff --git a/src/main/java/org/mybatis/dynamic/sql/util/SqlProviderAdapter.java b/src/main/java/org/mybatis/dynamic/sql/util/SqlProviderAdapter.java index fafcc6bda..2e129b611 100644 --- a/src/main/java/org/mybatis/dynamic/sql/util/SqlProviderAdapter.java +++ b/src/main/java/org/mybatis/dynamic/sql/util/SqlProviderAdapter.java @@ -17,7 +17,6 @@ import java.util.List; import java.util.Map; -import java.util.stream.Collectors; import org.mybatis.dynamic.sql.delete.render.DeleteStatementProvider; import org.mybatis.dynamic.sql.insert.render.GeneralInsertStatementProvider; @@ -76,7 +75,7 @@ public String insertMultipleWithGeneratedKeys(Map parameterMap) .map(Map.Entry::getValue) .filter(String.class::isInstance) .map(String.class::cast) - .collect(Collectors.toList()); + .toList(); if (entries.size() == 1) { return entries.get(0); diff --git a/src/main/java/org/mybatis/dynamic/sql/util/mybatis3/CommonSelectMapper.java b/src/main/java/org/mybatis/dynamic/sql/util/mybatis3/CommonSelectMapper.java index d7d67edc0..f0cfb72c0 100644 --- a/src/main/java/org/mybatis/dynamic/sql/util/mybatis3/CommonSelectMapper.java +++ b/src/main/java/org/mybatis/dynamic/sql/util/mybatis3/CommonSelectMapper.java @@ -20,7 +20,6 @@ import java.util.Map; import java.util.Optional; import java.util.function.Function; -import java.util.stream.Collectors; import org.apache.ibatis.annotations.SelectProvider; import org.mybatis.dynamic.sql.select.render.SelectStatementProvider; @@ -110,7 +109,7 @@ default List selectMany(SelectStatementProvider selectStatement, Function, R> rowMapper) { return selectManyMappedRows(selectStatement).stream() .map(rowMapper) - .collect(Collectors.toList()); + .toList(); } /** diff --git a/src/main/java/org/mybatis/dynamic/sql/util/spring/BatchInsertUtility.java b/src/main/java/org/mybatis/dynamic/sql/util/spring/BatchInsertUtility.java index 485868ba6..01b76b9a0 100644 --- a/src/main/java/org/mybatis/dynamic/sql/util/spring/BatchInsertUtility.java +++ b/src/main/java/org/mybatis/dynamic/sql/util/spring/BatchInsertUtility.java @@ -16,7 +16,6 @@ package org.mybatis.dynamic.sql.util.spring; import java.util.List; -import java.util.stream.Collectors; import org.springframework.jdbc.core.namedparam.SqlParameterSource; import org.springframework.jdbc.core.namedparam.SqlParameterSourceUtils; @@ -35,7 +34,7 @@ private BatchInsertUtility() {} public static SqlParameterSource[] createBatch(List rows) { List> tt = rows.stream() .map(RowHolder::new) - .collect(Collectors.toList()); + .toList(); return SqlParameterSourceUtils.createBatch(tt); } diff --git a/src/main/java/org/mybatis/dynamic/sql/where/condition/IsInCaseInsensitiveWhenPresent.java b/src/main/java/org/mybatis/dynamic/sql/where/condition/IsInCaseInsensitiveWhenPresent.java index b123d30c5..3fc3eca6f 100644 --- a/src/main/java/org/mybatis/dynamic/sql/where/condition/IsInCaseInsensitiveWhenPresent.java +++ b/src/main/java/org/mybatis/dynamic/sql/where/condition/IsInCaseInsensitiveWhenPresent.java @@ -21,7 +21,6 @@ import java.util.Objects; import java.util.function.Predicate; import java.util.function.UnaryOperator; -import java.util.stream.Collectors; import org.mybatis.dynamic.sql.AbstractListValueCondition; import org.mybatis.dynamic.sql.util.StringUtilities; @@ -35,7 +34,7 @@ public static IsInCaseInsensitiveWhenPresent empty() { } protected IsInCaseInsensitiveWhenPresent(Collection values) { - super(values.stream().filter(Objects::nonNull).collect(Collectors.toList())); + super(values.stream().filter(Objects::nonNull).toList()); } @Override diff --git a/src/main/java/org/mybatis/dynamic/sql/where/condition/IsInWhenPresent.java b/src/main/java/org/mybatis/dynamic/sql/where/condition/IsInWhenPresent.java index fc2994ea7..6e12a0437 100644 --- a/src/main/java/org/mybatis/dynamic/sql/where/condition/IsInWhenPresent.java +++ b/src/main/java/org/mybatis/dynamic/sql/where/condition/IsInWhenPresent.java @@ -21,7 +21,6 @@ import java.util.Objects; import java.util.function.Function; import java.util.function.Predicate; -import java.util.stream.Collectors; import org.mybatis.dynamic.sql.AbstractListValueCondition; @@ -35,7 +34,7 @@ public static IsInWhenPresent empty() { } protected IsInWhenPresent(Collection values) { - super(values.stream().filter(Objects::nonNull).collect(Collectors.toList())); + super(values.stream().filter(Objects::nonNull).toList()); } @Override diff --git a/src/main/java/org/mybatis/dynamic/sql/where/condition/IsNotInCaseInsensitiveWhenPresent.java b/src/main/java/org/mybatis/dynamic/sql/where/condition/IsNotInCaseInsensitiveWhenPresent.java index 58f0b347e..543ff7817 100644 --- a/src/main/java/org/mybatis/dynamic/sql/where/condition/IsNotInCaseInsensitiveWhenPresent.java +++ b/src/main/java/org/mybatis/dynamic/sql/where/condition/IsNotInCaseInsensitiveWhenPresent.java @@ -21,7 +21,6 @@ import java.util.Objects; import java.util.function.Predicate; import java.util.function.UnaryOperator; -import java.util.stream.Collectors; import org.mybatis.dynamic.sql.AbstractListValueCondition; import org.mybatis.dynamic.sql.util.StringUtilities; @@ -35,7 +34,7 @@ public static IsNotInCaseInsensitiveWhenPresent empty() { } protected IsNotInCaseInsensitiveWhenPresent(Collection values) { - super(values.stream().filter(Objects::nonNull).collect(Collectors.toList())); + super(values.stream().filter(Objects::nonNull).toList()); } @Override diff --git a/src/main/java/org/mybatis/dynamic/sql/where/condition/IsNotInWhenPresent.java b/src/main/java/org/mybatis/dynamic/sql/where/condition/IsNotInWhenPresent.java index 8115413ef..6917128ab 100644 --- a/src/main/java/org/mybatis/dynamic/sql/where/condition/IsNotInWhenPresent.java +++ b/src/main/java/org/mybatis/dynamic/sql/where/condition/IsNotInWhenPresent.java @@ -21,7 +21,6 @@ import java.util.Objects; import java.util.function.Function; import java.util.function.Predicate; -import java.util.stream.Collectors; import org.mybatis.dynamic.sql.AbstractListValueCondition; @@ -35,7 +34,7 @@ public static IsNotInWhenPresent empty() { } protected IsNotInWhenPresent(Collection values) { - super(values.stream().filter(Objects::nonNull).collect(Collectors.toList())); + super(values.stream().filter(Objects::nonNull).toList()); } @Override diff --git a/src/main/java/org/mybatis/dynamic/sql/where/render/CriterionRenderer.java b/src/main/java/org/mybatis/dynamic/sql/where/render/CriterionRenderer.java index 232b68c11..0e4325179 100644 --- a/src/main/java/org/mybatis/dynamic/sql/where/render/CriterionRenderer.java +++ b/src/main/java/org/mybatis/dynamic/sql/where/render/CriterionRenderer.java @@ -136,7 +136,7 @@ private FragmentAndParameters renderExists(ExistsCriterion criterion) { private List renderSubCriteria(List subCriteria) { return subCriteria.stream().map(this::renderAndOrCriteriaGroup) .flatMap(Optional::stream) - .collect(Collectors.toList()); + .toList(); } private Optional renderAndOrCriteriaGroup(AndOrCriteriaGroup criterion) { From e83b6f9d0550bff54f8bf2e96424857ddc9d48b6 Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Tue, 6 Aug 2024 11:07:02 -0400 Subject: [PATCH 5/9] Coverage --- .../sql/insert/render/BatchInsert.java | 2 +- .../sql/DeprecatedSortMethodsTest.java | 33 ++++++++++++++++++- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/mybatis/dynamic/sql/insert/render/BatchInsert.java b/src/main/java/org/mybatis/dynamic/sql/insert/render/BatchInsert.java index cde4ec626..5a3c22893 100644 --- a/src/main/java/org/mybatis/dynamic/sql/insert/render/BatchInsert.java +++ b/src/main/java/org/mybatis/dynamic/sql/insert/render/BatchInsert.java @@ -56,7 +56,7 @@ public String getInsertStatementSQL() { } public List getRecords() { - return Collections.unmodifiableList(records); + return records; } public static Builder withRecords(List records) { diff --git a/src/test/java/org/mybatis/dynamic/sql/DeprecatedSortMethodsTest.java b/src/test/java/org/mybatis/dynamic/sql/DeprecatedSortMethodsTest.java index 678d997d2..520783155 100644 --- a/src/test/java/org/mybatis/dynamic/sql/DeprecatedSortMethodsTest.java +++ b/src/test/java/org/mybatis/dynamic/sql/DeprecatedSortMethodsTest.java @@ -48,12 +48,43 @@ public String orderByName() { @Override public boolean isDescending() { - return true; + return false; } }; OrderByModel model = OrderByModel.of(List.of(ss)); + RenderingContext renderingContext = RenderingContext + .withRenderingStrategy(RenderingStrategies.MYBATIS3) + .withTableAliasCalculator(TableAliasCalculator.empty()) + .withStatementConfiguration(new StatementConfiguration()) + .build(); + OrderByRenderer renderer = new OrderByRenderer(renderingContext); + FragmentAndParameters fp = renderer.render(model); + assertThat(fp.fragment()).isEqualTo("order by id"); + } + + @Test + void bothMethodsExistDescending() { + SortSpecification ss = new SortSpecification() { + @Override + public SortSpecification descending() { + return this; + } + + @Override + public String orderByName() { + return "id"; + } + + @Override + public boolean isDescending() { + return true; + } + }; + + OrderByModel model = OrderByModel.of(List.of(ss)); + RenderingContext renderingContext = RenderingContext .withRenderingStrategy(RenderingStrategies.MYBATIS3) .withTableAliasCalculator(TableAliasCalculator.empty()) From 8b645112a8cc500573f1dc997efcbd2a4fdf2e66 Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Tue, 6 Aug 2024 11:24:26 -0400 Subject: [PATCH 6/9] Checkstyle and PMD Updates --- .../java/org/mybatis/dynamic/sql/SortSpecification.java | 4 ++-- .../java/org/mybatis/dynamic/sql/insert/BatchInsertDSL.java | 2 +- .../org/mybatis/dynamic/sql/insert/MultiRowInsertDSL.java | 2 +- .../org/mybatis/dynamic/sql/util/FragmentAndParameters.java | 2 +- .../sql/where/condition/IsInCaseInsensitiveWhenPresent.java | 6 ++++-- .../where/condition/IsNotInCaseInsensitiveWhenPresent.java | 6 ++++-- 6 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/mybatis/dynamic/sql/SortSpecification.java b/src/main/java/org/mybatis/dynamic/sql/SortSpecification.java index 87b986d27..48aee58c4 100644 --- a/src/main/java/org/mybatis/dynamic/sql/SortSpecification.java +++ b/src/main/java/org/mybatis/dynamic/sql/SortSpecification.java @@ -40,7 +40,7 @@ public interface SortSpecification { * * @return the order by phrase * @deprecated Please replace this method by overriding the more general "renderForOrderBy" method. Target for - * removal in release 2.1 + * removal in release 2.1 */ @Deprecated(since = "2.0", forRemoval = true) default String orderByName() { @@ -52,7 +52,7 @@ default String orderByName() { * * @return true if the SortSpecification should render as descending * @deprecated Please replace this method by overriding the more general "renderForOrderBy" method. Target for - * removal in release 2.1 + * removal in release 2.1 */ @Deprecated(since = "2.0", forRemoval = true) default boolean isDescending() { diff --git a/src/main/java/org/mybatis/dynamic/sql/insert/BatchInsertDSL.java b/src/main/java/org/mybatis/dynamic/sql/insert/BatchInsertDSL.java index 9b5f69cec..104557a4c 100644 --- a/src/main/java/org/mybatis/dynamic/sql/insert/BatchInsertDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/insert/BatchInsertDSL.java @@ -59,7 +59,7 @@ public BatchInsertModel build() { @SafeVarargs public static IntoGatherer insert(T... records) { - return BatchInsertDSL.insert(Arrays.asList(records)); + return insert(Arrays.asList(records)); } public static IntoGatherer insert(Collection records) { diff --git a/src/main/java/org/mybatis/dynamic/sql/insert/MultiRowInsertDSL.java b/src/main/java/org/mybatis/dynamic/sql/insert/MultiRowInsertDSL.java index 1b8feaca3..6976dabc9 100644 --- a/src/main/java/org/mybatis/dynamic/sql/insert/MultiRowInsertDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/insert/MultiRowInsertDSL.java @@ -58,7 +58,7 @@ public MultiRowInsertModel build() { @SafeVarargs public static IntoGatherer insert(T... records) { - return MultiRowInsertDSL.insert(Arrays.asList(records)); + return insert(Arrays.asList(records)); } public static IntoGatherer insert(Collection records) { diff --git a/src/main/java/org/mybatis/dynamic/sql/util/FragmentAndParameters.java b/src/main/java/org/mybatis/dynamic/sql/util/FragmentAndParameters.java index c6b65b3b0..4c240120c 100644 --- a/src/main/java/org/mybatis/dynamic/sql/util/FragmentAndParameters.java +++ b/src/main/java/org/mybatis/dynamic/sql/util/FragmentAndParameters.java @@ -46,7 +46,7 @@ public Map parameters() { * @return a new instance with the same parameters and a transformed fragment */ public FragmentAndParameters mapFragment(UnaryOperator mapper) { - return FragmentAndParameters.withFragment(mapper.apply(fragment)) + return withFragment(mapper.apply(fragment)) .withParameters(parameters) .build(); } diff --git a/src/main/java/org/mybatis/dynamic/sql/where/condition/IsInCaseInsensitiveWhenPresent.java b/src/main/java/org/mybatis/dynamic/sql/where/condition/IsInCaseInsensitiveWhenPresent.java index 3fc3eca6f..356fb034a 100644 --- a/src/main/java/org/mybatis/dynamic/sql/where/condition/IsInCaseInsensitiveWhenPresent.java +++ b/src/main/java/org/mybatis/dynamic/sql/where/condition/IsInCaseInsensitiveWhenPresent.java @@ -27,7 +27,8 @@ public class IsInCaseInsensitiveWhenPresent extends AbstractListValueCondition implements CaseInsensitiveVisitableCondition { - private static final IsInCaseInsensitiveWhenPresent EMPTY = new IsInCaseInsensitiveWhenPresent(Collections.emptyList()); + private static final IsInCaseInsensitiveWhenPresent EMPTY = + new IsInCaseInsensitiveWhenPresent(Collections.emptyList()); public static IsInCaseInsensitiveWhenPresent empty() { return EMPTY; @@ -44,7 +45,8 @@ public String operator() { @Override public IsInCaseInsensitiveWhenPresent filter(Predicate predicate) { - return filterSupport(predicate, IsInCaseInsensitiveWhenPresent::new, this, IsInCaseInsensitiveWhenPresent::empty); + return filterSupport(predicate, IsInCaseInsensitiveWhenPresent::new, this, + IsInCaseInsensitiveWhenPresent::empty); } /** diff --git a/src/main/java/org/mybatis/dynamic/sql/where/condition/IsNotInCaseInsensitiveWhenPresent.java b/src/main/java/org/mybatis/dynamic/sql/where/condition/IsNotInCaseInsensitiveWhenPresent.java index 543ff7817..7f254eedd 100644 --- a/src/main/java/org/mybatis/dynamic/sql/where/condition/IsNotInCaseInsensitiveWhenPresent.java +++ b/src/main/java/org/mybatis/dynamic/sql/where/condition/IsNotInCaseInsensitiveWhenPresent.java @@ -27,7 +27,8 @@ public class IsNotInCaseInsensitiveWhenPresent extends AbstractListValueCondition implements CaseInsensitiveVisitableCondition { - private static final IsNotInCaseInsensitiveWhenPresent EMPTY = new IsNotInCaseInsensitiveWhenPresent(Collections.emptyList()); + private static final IsNotInCaseInsensitiveWhenPresent EMPTY = + new IsNotInCaseInsensitiveWhenPresent(Collections.emptyList()); public static IsNotInCaseInsensitiveWhenPresent empty() { return EMPTY; @@ -44,7 +45,8 @@ public String operator() { @Override public IsNotInCaseInsensitiveWhenPresent filter(Predicate predicate) { - return filterSupport(predicate, IsNotInCaseInsensitiveWhenPresent::new, this, IsNotInCaseInsensitiveWhenPresent::empty); + return filterSupport(predicate, IsNotInCaseInsensitiveWhenPresent::new, + this, IsNotInCaseInsensitiveWhenPresent::empty); } /** From 1d2dc669b0092896058efbf2a38c61b54f585aeb Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Tue, 6 Aug 2024 11:40:51 -0400 Subject: [PATCH 7/9] CPD Fixes --- .../java/org/mybatis/dynamic/sql/insert/BatchInsertDSL.java | 4 ++-- .../org/mybatis/dynamic/sql/insert/MultiRowInsertDSL.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/mybatis/dynamic/sql/insert/BatchInsertDSL.java b/src/main/java/org/mybatis/dynamic/sql/insert/BatchInsertDSL.java index 104557a4c..ba912e5a6 100644 --- a/src/main/java/org/mybatis/dynamic/sql/insert/BatchInsertDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/insert/BatchInsertDSL.java @@ -58,11 +58,11 @@ public BatchInsertModel build() { } @SafeVarargs - public static IntoGatherer insert(T... records) { + public static BatchInsertDSL.IntoGatherer insert(T... records) { return insert(Arrays.asList(records)); } - public static IntoGatherer insert(Collection records) { + public static BatchInsertDSL.IntoGatherer insert(Collection records) { return new IntoGatherer<>(records); } diff --git a/src/main/java/org/mybatis/dynamic/sql/insert/MultiRowInsertDSL.java b/src/main/java/org/mybatis/dynamic/sql/insert/MultiRowInsertDSL.java index 6976dabc9..7c0530a2a 100644 --- a/src/main/java/org/mybatis/dynamic/sql/insert/MultiRowInsertDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/insert/MultiRowInsertDSL.java @@ -57,11 +57,11 @@ public MultiRowInsertModel build() { } @SafeVarargs - public static IntoGatherer insert(T... records) { + public static MultiRowInsertDSL.IntoGatherer insert(T... records) { return insert(Arrays.asList(records)); } - public static IntoGatherer insert(Collection records) { + public static MultiRowInsertDSL.IntoGatherer insert(Collection records) { return new IntoGatherer<>(records); } From 4b89c48e6e08636f866e531ed7ff517a2c901c65 Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Tue, 6 Aug 2024 12:53:03 -0400 Subject: [PATCH 8/9] Don't need Hamcrest anymore --- pom.xml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/pom.xml b/pom.xml index 5d5447a8f..d2ce1ecdd 100644 --- a/pom.xml +++ b/pom.xml @@ -164,14 +164,6 @@ 1.5.6 test - - - org.hamcrest - hamcrest - 3.0 - test - - org.testcontainers postgresql From dca5d3dadc52b5d22d195a35dba3a1001f44e54d Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Tue, 6 Aug 2024 14:48:07 -0400 Subject: [PATCH 9/9] Docs --- CHANGELOG.md | 1 + src/site/markdown/docs/caseExpressions.md | 4 ++-- src/site/markdown/docs/kotlinCaseExpressions.md | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 31e9fa8b3..3323eafdb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ Significant changes: - The library now requires Java 17 - Deprecated code from prior releases is removed +- Allow CASE expressions in ORDER BY Clauses ## Release 1.5.2 - June 3, 2024 diff --git a/src/site/markdown/docs/caseExpressions.md b/src/site/markdown/docs/caseExpressions.md index 9b83d4f3e..3f711e626 100644 --- a/src/site/markdown/docs/caseExpressions.md +++ b/src/site/markdown/docs/caseExpressions.md @@ -3,9 +3,9 @@ Support for case expressions was added in version 1.5.1. For information about case expressions in the Kotlin DSL, see the [Kotlin Case Expressions](kotlinCaseExpressions.md) page. -## Case Statements in SQL +## Case Expressions in SQL The library supports different types of case expressions - a "simple" case expression, and a "searched" case -expressions. +expressions. Case expressions can be used in many places including select lists, order by phrases, etc. A simple case expression checks the values of a single column. It looks like this: diff --git a/src/site/markdown/docs/kotlinCaseExpressions.md b/src/site/markdown/docs/kotlinCaseExpressions.md index 5366db40b..d0fdb4b4d 100644 --- a/src/site/markdown/docs/kotlinCaseExpressions.md +++ b/src/site/markdown/docs/kotlinCaseExpressions.md @@ -3,9 +3,9 @@ Support for case expressions was added in version 1.5.1. For information about case expressions in the Java DSL, see the [Java Case Expressions](caseExpressions.md) page. -## Case Statements in SQL +## Case Expressions in SQL The library supports different types of case expressions - a "simple" case expression, and a "searched" case -expressions. +expressions. Case expressions can be used in many places including select lists, order by phrases, etc. A simple case expression checks the values of a single column. It looks like this: