From 226ac5e15f99cb0fe7671cf21457765011f5262f Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Sun, 14 Aug 2022 18:26:40 -0400 Subject: [PATCH 01/23] Update license header file for new parent --- license.txt => LICENSE_HEADER | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename license.txt => LICENSE_HEADER (100%) diff --git a/license.txt b/LICENSE_HEADER similarity index 100% rename from license.txt rename to LICENSE_HEADER From d3427d1b7cefa30eb938c2138126c8a4b476f614 Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Mon, 15 Aug 2022 09:16:08 -0400 Subject: [PATCH 02/23] Initial Work on Statement Configuration --- .../dynamic/sql/GlobalConfiguration.java | 45 ++++++++++++++++ .../dynamic/sql/StatementConfiguration.java | 48 +++++++++++++++++ .../mybatis/dynamic/sql/delete/DeleteDSL.java | 9 +++- .../UnrenderableWhereClauseException.java | 38 ++++++++++++++ .../mybatis/dynamic/sql/select/CountDSL.java | 11 ++-- .../sql/select/QueryExpressionDSL.java | 21 ++++++-- .../mybatis/dynamic/sql/select/SelectDSL.java | 13 ++++- .../mybatis/dynamic/sql/update/UpdateDSL.java | 9 +++- .../sql/util/ConfigurableStatement.java | 24 +++++++++ .../dynamic/sql/where/AbstractWhereDSL.java | 20 +++++++- .../mybatis/dynamic/sql/where/WhereDSL.java | 9 ++-- .../mybatis/dynamic/sql/where/WhereModel.java | 17 ++++++- .../sql/where/render/WhereRenderer.java | 9 +++- .../sql/util/kotlin/KotlinBaseBuilders.kt | 12 +++-- .../examples/animal/data/AnimalDataTest.java | 2 + .../OptionalConditionsAnimalDataTest.java | 4 +- ...onditionsWithPredicatesAnimalDataTest.java | 2 + .../complexquery/ComplexQueryTest.java | 3 +- .../examples/emptywhere/EmptyWhereTest.java | 5 ++ .../java/examples/joins/JoinMapperTest.java | 2 +- src/test/java/issues/gh105/Issue105Test.java | 25 +++++++++ .../sql/select/SelectStatementTest.java | 6 ++- .../render/OptionalCriterionRenderTest.java | 5 ++ .../spring/canonical/InfixElementsTest.kt | 51 ++++++++++++++++++- .../spring/canonical/KotlinElementsTest.kt | 10 +++- 25 files changed, 371 insertions(+), 29 deletions(-) create mode 100644 src/main/java/org/mybatis/dynamic/sql/GlobalConfiguration.java create mode 100644 src/main/java/org/mybatis/dynamic/sql/StatementConfiguration.java create mode 100644 src/main/java/org/mybatis/dynamic/sql/exception/UnrenderableWhereClauseException.java create mode 100644 src/main/java/org/mybatis/dynamic/sql/util/ConfigurableStatement.java diff --git a/src/main/java/org/mybatis/dynamic/sql/GlobalConfiguration.java b/src/main/java/org/mybatis/dynamic/sql/GlobalConfiguration.java new file mode 100644 index 000000000..26bc2f327 --- /dev/null +++ b/src/main/java/org/mybatis/dynamic/sql/GlobalConfiguration.java @@ -0,0 +1,45 @@ +/* + * Copyright 2016-2022 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; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +// TODO - read initial value from a properties file! +public class GlobalConfiguration { + private static boolean unrenderableWhereClauseAllowed = false; + + static { + String propertyFile = "mybatis-dynamic-sql.properties"; + try (InputStream is = GlobalConfiguration.class.getResourceAsStream(propertyFile)) { + if (is != null) { + Properties p = new Properties(); + p.load(is); + String value = p.getProperty("unrenderableWhereClauseAllowed"); + if (value != null) { + unrenderableWhereClauseAllowed = Boolean.parseBoolean(value); + } + } + } catch (IOException e) { + // ignore + } + } + + public static boolean getUnrenderableWhereClauseAllowed() { + return unrenderableWhereClauseAllowed; + } +} diff --git a/src/main/java/org/mybatis/dynamic/sql/StatementConfiguration.java b/src/main/java/org/mybatis/dynamic/sql/StatementConfiguration.java new file mode 100644 index 000000000..db9e09b08 --- /dev/null +++ b/src/main/java/org/mybatis/dynamic/sql/StatementConfiguration.java @@ -0,0 +1,48 @@ +/* + * Copyright 2016-2022 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; + +/** + * This class can be used to change some behaviors of the framework. Every configurable statement + * contains a unique instance of this class, so changes here will only impact a single statement. + * If you intend to change the behavior for all statements, use the {@link GlobalConfiguration} + * configuration class. + * + *
+ *
unrenderableWhereClauseAllowed
+ *
If false (default), the framework will throw an + * {@link org.mybatis.dynamic.sql.exception.UnrenderableWhereClauseException} + * if a where clause is specified in the statement, but it fails to render because all + * optional conditions do not render. For example, if an "in" condition specifies an + * empty list of values. + *
+ *
+ * + * @see GlobalConfiguration + * @since 1.4.1 + * @author Jeff Butler + */ +public class StatementConfiguration { + private boolean unrenderableWhereClauseAllowed = GlobalConfiguration.getUnrenderableWhereClauseAllowed(); + + public boolean getUnrenderableWhereClauseAllowed() { + return unrenderableWhereClauseAllowed; + } + + public void setUnrenderableWhereClauseAllowed(boolean unrenderableWhereClauseAllowed) { + this.unrenderableWhereClauseAllowed = unrenderableWhereClauseAllowed; + } +} diff --git a/src/main/java/org/mybatis/dynamic/sql/delete/DeleteDSL.java b/src/main/java/org/mybatis/dynamic/sql/delete/DeleteDSL.java index 4c06507b9..d47c1f25b 100644 --- a/src/main/java/org/mybatis/dynamic/sql/delete/DeleteDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/delete/DeleteDSL.java @@ -20,6 +20,7 @@ import org.jetbrains.annotations.NotNull; import org.mybatis.dynamic.sql.SqlTable; +import org.mybatis.dynamic.sql.StatementConfiguration; import org.mybatis.dynamic.sql.util.Buildable; import org.mybatis.dynamic.sql.where.AbstractWhereDSL; import org.mybatis.dynamic.sql.where.AbstractWhereSupport; @@ -30,12 +31,14 @@ public class DeleteDSL extends AbstractWhereSupport.DeleteWhereB private final Function adapterFunction; private final SqlTable table; private final String tableAlias; - private final DeleteWhereBuilder whereBuilder = new DeleteWhereBuilder(); + private final DeleteWhereBuilder whereBuilder; + private final StatementConfiguration statementConfiguration = new StatementConfiguration(); private DeleteDSL(SqlTable table, String tableAlias, Function adapterFunction) { this.table = Objects.requireNonNull(table); this.tableAlias = tableAlias; this.adapterFunction = Objects.requireNonNull(adapterFunction); + whereBuilder = new DeleteWhereBuilder(); } @Override @@ -74,7 +77,9 @@ public static DeleteDSL deleteFrom(SqlTable table, String tableAlia public class DeleteWhereBuilder extends AbstractWhereDSL implements Buildable { - private DeleteWhereBuilder() {} + private DeleteWhereBuilder() { + super(statementConfiguration); + } @NotNull @Override diff --git a/src/main/java/org/mybatis/dynamic/sql/exception/UnrenderableWhereClauseException.java b/src/main/java/org/mybatis/dynamic/sql/exception/UnrenderableWhereClauseException.java new file mode 100644 index 000000000..0c4b925d3 --- /dev/null +++ b/src/main/java/org/mybatis/dynamic/sql/exception/UnrenderableWhereClauseException.java @@ -0,0 +1,38 @@ +/* + * Copyright 2016-2022 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.exception; + +/** + * This exception is thrown when the where clause in a statement will not render. + * This can happen if all the optional conditions in a where clause fail to + * render - for example, if an "in" condition specifies an empty list. + *

+ * By default, the framework will throw this exception if a where clause + * fails to render. A where clause that fails to render can be very dangerous in that + * it could cause all rows in a table to be affected by a statement - for example, + * all rows could be deleted. + *

+ * If you intend to allow an unrenderable where clause, then configure the + * statement to allow it, or change the global configuration. + * + * @see org.mybatis.dynamic.sql.GlobalConfiguration + * @see org.mybatis.dynamic.sql.StatementConfiguration + * @since 1.4.1 + * @author Jeff Butler + */ +public class UnrenderableWhereClauseException extends RuntimeException { + public UnrenderableWhereClauseException() {} +} diff --git a/src/main/java/org/mybatis/dynamic/sql/select/CountDSL.java b/src/main/java/org/mybatis/dynamic/sql/select/CountDSL.java index e3f80ec17..8a87a12bc 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/CountDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/CountDSL.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2021 the original author or authors. + * Copyright 2016-2022 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. @@ -22,6 +22,7 @@ import org.mybatis.dynamic.sql.BasicColumn; import org.mybatis.dynamic.sql.SqlBuilder; import org.mybatis.dynamic.sql.SqlTable; +import org.mybatis.dynamic.sql.StatementConfiguration; import org.mybatis.dynamic.sql.util.Buildable; import org.mybatis.dynamic.sql.where.AbstractWhereDSL; import org.mybatis.dynamic.sql.where.WhereModel; @@ -39,13 +40,15 @@ public class CountDSL extends AbstractQueryExpressionDSL.CountWhe implements Buildable { private final Function adapterFunction; - private final CountWhereBuilder whereBuilder = new CountWhereBuilder(); + private final CountWhereBuilder whereBuilder; private final BasicColumn countColumn; + private final StatementConfiguration statementConfiguration = new StatementConfiguration(); private CountDSL(BasicColumn countColumn, SqlTable table, Function adapterFunction) { super(table); this.countColumn = Objects.requireNonNull(countColumn); this.adapterFunction = Objects.requireNonNull(adapterFunction); + whereBuilder = new CountWhereBuilder(statementConfiguration); } @Override @@ -118,7 +121,9 @@ public CountDSL from(SqlTable table) { public class CountWhereBuilder extends AbstractWhereDSL implements Buildable { - private CountWhereBuilder() {} + private CountWhereBuilder(StatementConfiguration statementConfiguration) { + super(statementConfiguration); + } @NotNull @Override diff --git a/src/main/java/org/mybatis/dynamic/sql/select/QueryExpressionDSL.java b/src/main/java/org/mybatis/dynamic/sql/select/QueryExpressionDSL.java index 6061babe6..e462ee6d6 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/QueryExpressionDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/QueryExpressionDSL.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2021 the original author or authors. + * Copyright 2016-2022 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. @@ -20,31 +20,35 @@ import java.util.Collection; import java.util.List; import java.util.Objects; +import java.util.function.Consumer; import org.jetbrains.annotations.NotNull; import org.mybatis.dynamic.sql.BasicColumn; import org.mybatis.dynamic.sql.SortSpecification; import org.mybatis.dynamic.sql.SqlTable; +import org.mybatis.dynamic.sql.StatementConfiguration; import org.mybatis.dynamic.sql.TableExpression; import org.mybatis.dynamic.sql.select.join.JoinCondition; import org.mybatis.dynamic.sql.select.join.JoinCriterion; import org.mybatis.dynamic.sql.select.join.JoinSpecification; import org.mybatis.dynamic.sql.select.join.JoinType; import org.mybatis.dynamic.sql.util.Buildable; +import org.mybatis.dynamic.sql.util.ConfigurableStatement; import org.mybatis.dynamic.sql.where.AbstractWhereDSL; import org.mybatis.dynamic.sql.where.AbstractWhereSupport; import org.mybatis.dynamic.sql.where.WhereModel; public class QueryExpressionDSL extends AbstractQueryExpressionDSL.QueryExpressionWhereBuilder, QueryExpressionDSL> - implements Buildable { + implements Buildable, ConfigurableStatement> { private final String connector; private final SelectDSL selectDSL; private final boolean isDistinct; private final List selectList; - private final QueryExpressionWhereBuilder whereBuilder = new QueryExpressionWhereBuilder(); + private final QueryExpressionWhereBuilder whereBuilder; private GroupByModel groupByModel; + private final StatementConfiguration statementConfiguration = new StatementConfiguration(); QueryExpressionDSL(FromGatherer fromGatherer, TableExpression table) { super(table); @@ -52,6 +56,7 @@ public class QueryExpressionDSL selectList = fromGatherer.selectList; isDistinct = fromGatherer.isDistinct; selectDSL = Objects.requireNonNull(fromGatherer.selectDSL); + whereBuilder = new QueryExpressionWhereBuilder(statementConfiguration); } QueryExpressionDSL(FromGatherer fromGatherer, SqlTable table, String tableAlias) { @@ -64,6 +69,12 @@ public QueryExpressionWhereBuilder where() { return whereBuilder; } + @Override + public QueryExpressionDSL configureStatement(Consumer consumer) { + consumer.accept(statementConfiguration); + return this; + } + @NotNull @Override public R build() { @@ -240,7 +251,9 @@ public FromGatherer build() { public class QueryExpressionWhereBuilder extends AbstractWhereDSL implements Buildable { - private QueryExpressionWhereBuilder() {} + private QueryExpressionWhereBuilder(StatementConfiguration statementConfiguration) { + super(statementConfiguration); + } public UnionBuilder union() { return QueryExpressionDSL.this.union(); 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 5627734d0..cc4088e29 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/SelectDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/SelectDSL.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2022 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. @@ -20,6 +20,7 @@ import java.util.Collection; import java.util.List; import java.util.Objects; +import java.util.function.Consumer; import java.util.function.Function; import java.util.stream.Collectors; @@ -27,9 +28,11 @@ import org.mybatis.dynamic.sql.BasicColumn; import org.mybatis.dynamic.sql.SortSpecification; import org.mybatis.dynamic.sql.SqlTable; +import org.mybatis.dynamic.sql.StatementConfiguration; import org.mybatis.dynamic.sql.TableExpression; import org.mybatis.dynamic.sql.select.QueryExpressionDSL.FromGatherer; import org.mybatis.dynamic.sql.util.Buildable; +import org.mybatis.dynamic.sql.util.ConfigurableStatement; /** * Implements a SQL DSL for building select statements. @@ -38,7 +41,7 @@ * * @param the type of model produced by this builder, typically SelectModel */ -public class SelectDSL implements Buildable { +public class SelectDSL implements Buildable, ConfigurableStatement> { private final Function adapterFunction; private final List> queryExpressions = new ArrayList<>(); @@ -125,6 +128,12 @@ public FetchFirstFinisher fetchFirst(long fetchFirstRows) { return new FetchFirstFinisher(); } + @Override + public SelectDSL configureStatement(Consumer consumer) { + queryExpressions.forEach(q -> q.configureStatement(consumer)); + return this; + } + @NotNull @Override public R build() { diff --git a/src/main/java/org/mybatis/dynamic/sql/update/UpdateDSL.java b/src/main/java/org/mybatis/dynamic/sql/update/UpdateDSL.java index 870f6dbcf..622038b04 100644 --- a/src/main/java/org/mybatis/dynamic/sql/update/UpdateDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/update/UpdateDSL.java @@ -25,6 +25,7 @@ import org.mybatis.dynamic.sql.BasicColumn; import org.mybatis.dynamic.sql.SqlColumn; import org.mybatis.dynamic.sql.SqlTable; +import org.mybatis.dynamic.sql.StatementConfiguration; import org.mybatis.dynamic.sql.select.SelectModel; import org.mybatis.dynamic.sql.util.AbstractColumnMapping; import org.mybatis.dynamic.sql.util.Buildable; @@ -46,12 +47,14 @@ public class UpdateDSL extends AbstractWhereSupport.UpdateWhereB private final List columnMappings = new ArrayList<>(); private final SqlTable table; private final String tableAlias; - private final UpdateWhereBuilder whereBuilder = new UpdateWhereBuilder(); + private final UpdateWhereBuilder whereBuilder; + private final StatementConfiguration statementConfiguration = new StatementConfiguration(); private UpdateDSL(SqlTable table, String tableAlias, Function adapterFunction) { this.table = Objects.requireNonNull(table); this.tableAlias = tableAlias; this.adapterFunction = Objects.requireNonNull(adapterFunction); + whereBuilder = new UpdateWhereBuilder(statementConfiguration); } public SetClauseFinisher set(SqlColumn column) { @@ -155,7 +158,9 @@ public UpdateDSL equalToWhenPresent(Supplier valueSupplier) { public class UpdateWhereBuilder extends AbstractWhereDSL implements Buildable { - private UpdateWhereBuilder() {} + private UpdateWhereBuilder(StatementConfiguration statementConfiguration) { + super(statementConfiguration); + } @NotNull @Override diff --git a/src/main/java/org/mybatis/dynamic/sql/util/ConfigurableStatement.java b/src/main/java/org/mybatis/dynamic/sql/util/ConfigurableStatement.java new file mode 100644 index 000000000..c723c06a7 --- /dev/null +++ b/src/main/java/org/mybatis/dynamic/sql/util/ConfigurableStatement.java @@ -0,0 +1,24 @@ +/* + * Copyright 2016-2022 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.util; + +import org.mybatis.dynamic.sql.StatementConfiguration; + +import java.util.function.Consumer; + +public interface ConfigurableStatement { + R configureStatement(Consumer consumer); +} diff --git a/src/main/java/org/mybatis/dynamic/sql/where/AbstractWhereDSL.java b/src/main/java/org/mybatis/dynamic/sql/where/AbstractWhereDSL.java index de46fd15c..950851aa6 100644 --- a/src/main/java/org/mybatis/dynamic/sql/where/AbstractWhereDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/where/AbstractWhereDSL.java @@ -18,6 +18,8 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Objects; +import java.util.function.Consumer; import org.jetbrains.annotations.NotNull; import org.mybatis.dynamic.sql.AndOrCriteriaGroup; @@ -27,12 +29,26 @@ import org.mybatis.dynamic.sql.ExistsCriterion; import org.mybatis.dynamic.sql.ExistsPredicate; import org.mybatis.dynamic.sql.SqlCriterion; +import org.mybatis.dynamic.sql.StatementConfiguration; import org.mybatis.dynamic.sql.VisitableCondition; +import org.mybatis.dynamic.sql.util.ConfigurableStatement; -public abstract class AbstractWhereDSL> { +public abstract class AbstractWhereDSL> implements ConfigurableStatement { private SqlCriterion initialCriterion; // WARNING - may be null! private final List subCriteria = new ArrayList<>(); + private final StatementConfiguration statementConfiguration; + + protected AbstractWhereDSL(StatementConfiguration statementConfiguration) { + this.statementConfiguration = Objects.requireNonNull(statementConfiguration); + } + + @Override + public T configureStatement(Consumer consumer) { + consumer.accept(statementConfiguration); + return getThis(); + } + @NotNull public T where(BindableColumn column, VisitableCondition condition, AndOrCriteriaGroup...subCriteria) { @@ -172,7 +188,7 @@ public T or(List criteria) { } protected WhereModel internalBuild() { - return new WhereModel(initialCriterion, subCriteria); + return new WhereModel(initialCriterion, subCriteria, statementConfiguration); } private SqlCriterion buildCriterion(BindableColumn column, VisitableCondition condition) { diff --git a/src/main/java/org/mybatis/dynamic/sql/where/WhereDSL.java b/src/main/java/org/mybatis/dynamic/sql/where/WhereDSL.java index a5eb3332b..7d09346c5 100644 --- a/src/main/java/org/mybatis/dynamic/sql/where/WhereDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/where/WhereDSL.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2022 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. @@ -15,9 +15,12 @@ */ package org.mybatis.dynamic.sql.where; -public class WhereDSL extends AbstractWhereDSL { +import org.mybatis.dynamic.sql.StatementConfiguration; - private WhereDSL() {} +public class WhereDSL extends AbstractWhereDSL { + private WhereDSL() { + super(new StatementConfiguration()); + } @Override protected WhereDSL getThis() { diff --git a/src/main/java/org/mybatis/dynamic/sql/where/WhereModel.java b/src/main/java/org/mybatis/dynamic/sql/where/WhereModel.java index f102ddc03..a0b01c4c4 100644 --- a/src/main/java/org/mybatis/dynamic/sql/where/WhereModel.java +++ b/src/main/java/org/mybatis/dynamic/sql/where/WhereModel.java @@ -18,11 +18,13 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.Optional; import java.util.concurrent.atomic.AtomicInteger; import org.mybatis.dynamic.sql.AndOrCriteriaGroup; import org.mybatis.dynamic.sql.SqlCriterion; +import org.mybatis.dynamic.sql.StatementConfiguration; import org.mybatis.dynamic.sql.render.RenderingStrategy; import org.mybatis.dynamic.sql.render.TableAliasCalculator; import org.mybatis.dynamic.sql.where.render.WhereClauseProvider; @@ -35,9 +37,13 @@ public class WhereModel { private final SqlCriterion initialCriterion; private final List subCriteria = new ArrayList<>(); - public WhereModel(SqlCriterion initialCriterion, List subCriteria) { + private final StatementConfiguration statementConfiguration; + + public WhereModel(SqlCriterion initialCriterion, List subCriteria, + StatementConfiguration statementConfiguration) { this.initialCriterion = initialCriterion; this.subCriteria.addAll(subCriteria); + this.statementConfiguration = Objects.requireNonNull(statementConfiguration); } public Optional initialCriterion() { @@ -48,6 +54,15 @@ public List subCriteria() { return Collections.unmodifiableList(subCriteria); } + public boolean isUnrenderableClauseAllowed() { + // if no criteria were specified, then no where clause was expected + if (initialCriterion == null && subCriteria.isEmpty()) { + return true; + } + + return statementConfiguration.getUnrenderableWhereClauseAllowed(); + } + /** * Renders a where clause without table aliases. * diff --git a/src/main/java/org/mybatis/dynamic/sql/where/render/WhereRenderer.java b/src/main/java/org/mybatis/dynamic/sql/where/render/WhereRenderer.java index 53f36b559..552f60d96 100644 --- a/src/main/java/org/mybatis/dynamic/sql/where/render/WhereRenderer.java +++ b/src/main/java/org/mybatis/dynamic/sql/where/render/WhereRenderer.java @@ -21,6 +21,7 @@ import java.util.stream.Collectors; import org.mybatis.dynamic.sql.SqlCriterion; +import org.mybatis.dynamic.sql.exception.UnrenderableWhereClauseException; import org.mybatis.dynamic.sql.render.RenderingStrategy; import org.mybatis.dynamic.sql.render.TableAliasCalculator; import org.mybatis.dynamic.sql.util.FragmentCollector; @@ -42,12 +43,18 @@ private WhereRenderer(Builder builder) { } public Optional render() { - return whereModel.initialCriterion().map(this::renderWithInitialCriterion) + Optional whereClause = whereModel.initialCriterion().map(this::renderWithInitialCriterion) .orElseGet(this::renderWithoutInitialCriterion) .map(rc -> WhereClauseProvider.withWhereClause(rc.fragmentAndParameters().fragment()) .withParameters(rc.fragmentAndParameters().parameters()) .build() ); + + if (whereClause.isPresent() || whereModel.isUnrenderableClauseAllowed()) { + return whereClause; + } + + throw new UnrenderableWhereClauseException(); } private Optional renderWithInitialCriterion(SqlCriterion initialCriterion) { diff --git a/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/KotlinBaseBuilders.kt b/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/KotlinBaseBuilders.kt index 8de59a32e..375af1bcc 100644 --- a/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/KotlinBaseBuilders.kt +++ b/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/KotlinBaseBuilders.kt @@ -19,6 +19,7 @@ import org.mybatis.dynamic.sql.BindableColumn import org.mybatis.dynamic.sql.AndOrCriteriaGroup import org.mybatis.dynamic.sql.ExistsPredicate import org.mybatis.dynamic.sql.SqlTable +import org.mybatis.dynamic.sql.StatementConfiguration import org.mybatis.dynamic.sql.VisitableCondition import org.mybatis.dynamic.sql.select.AbstractQueryExpressionDSL import org.mybatis.dynamic.sql.where.AbstractWhereDSL @@ -38,13 +39,18 @@ fun WhereApplier.andThen(after: WhereApplier): WhereApplier = { @MyBatisDslMarker @Suppress("TooManyFunctions") abstract class KotlinBaseBuilder> { + + fun configureStatement(c: StatementConfiguration.() -> Unit) { + getDsl().where().configureStatement(c) + } + fun where(criteria: GroupingCriteriaReceiver): Unit = with(GroupingCriteriaCollector().apply(criteria)) { this@KotlinBaseBuilder.getDsl().where(initialCriterion, subCriteria) } fun where(criteria: List) { - this@KotlinBaseBuilder.getDsl().where(criteria) + getDsl().where(criteria) } fun and(criteria: GroupingCriteriaReceiver): Unit = @@ -53,7 +59,7 @@ abstract class KotlinBaseBuilder> { } fun and(criteria: List) { - this@KotlinBaseBuilder.getDsl().where().and(criteria) + getDsl().where().and(criteria) } fun or(criteria: GroupingCriteriaReceiver): Unit = @@ -62,7 +68,7 @@ abstract class KotlinBaseBuilder> { } fun or(criteria: List) { - this@KotlinBaseBuilder.getDsl().where().or(criteria) + getDsl().where().or(criteria) } fun applyWhere(whereApplier: WhereApplier) = whereApplier.invoke(this) diff --git a/src/test/java/examples/animal/data/AnimalDataTest.java b/src/test/java/examples/animal/data/AnimalDataTest.java index 69b4601c7..573aa1c53 100644 --- a/src/test/java/examples/animal/data/AnimalDataTest.java +++ b/src/test/java/examples/animal/data/AnimalDataTest.java @@ -651,6 +651,7 @@ void testInConditionWithEventuallyEmptyList() { SelectStatementProvider selectStatement = select(id, animalName, bodyWeight, brainWeight) .from(animalData) .where(id, isIn(null, 22, null).filter(Objects::nonNull).filter(i -> i != 22)) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -766,6 +767,7 @@ void testNotInConditionWithEventuallyEmptyList() { SelectStatementProvider selectStatement = select(id, animalName, bodyWeight, brainWeight) .from(animalData) .where(id, isNotIn(null, 22, null).filter(Objects::nonNull).filter(i -> i != 22)) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); diff --git a/src/test/java/examples/animal/data/OptionalConditionsAnimalDataTest.java b/src/test/java/examples/animal/data/OptionalConditionsAnimalDataTest.java index dbceeec5a..74704389f 100644 --- a/src/test/java/examples/animal/data/OptionalConditionsAnimalDataTest.java +++ b/src/test/java/examples/animal/data/OptionalConditionsAnimalDataTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2022 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. @@ -51,6 +51,7 @@ class OptionalConditionsAnimalDataTest { void setup() throws Exception { Class.forName(JDBC_DRIVER); InputStream is = getClass().getResourceAsStream("/examples/animal/data/CreateAnimalData.sql"); + assert is != null; try (Connection connection = DriverManager.getConnection(JDBC_URL, "sa", "")) { ScriptRunner sr = new ScriptRunner(connection); sr.setLogWriter(null); @@ -72,6 +73,7 @@ void testAllIgnored() { .from(animalData) .where(id, isGreaterThanWhenPresent(NULL_INTEGER)) // the where clause should not render .orderBy(id) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); List animals = mapper.selectMany(selectStatement); diff --git a/src/test/java/examples/animal/data/OptionalConditionsWithPredicatesAnimalDataTest.java b/src/test/java/examples/animal/data/OptionalConditionsWithPredicatesAnimalDataTest.java index 3207a3ba2..5c3841f3d 100644 --- a/src/test/java/examples/animal/data/OptionalConditionsWithPredicatesAnimalDataTest.java +++ b/src/test/java/examples/animal/data/OptionalConditionsWithPredicatesAnimalDataTest.java @@ -57,6 +57,7 @@ class OptionalConditionsWithPredicatesAnimalDataTest { void setup() throws Exception { Class.forName(JDBC_DRIVER); InputStream is = getClass().getResourceAsStream("/examples/animal/data/CreateAnimalData.sql"); + assert is != null; try (Connection connection = DriverManager.getConnection(JDBC_URL, "sa", "")) { ScriptRunner sr = new ScriptRunner(connection); sr.setLogWriter(null); @@ -78,6 +79,7 @@ void testAllIgnored() { .from(animalData) .where(id, isGreaterThan(NULL_INTEGER).filter(Objects::nonNull)) // the where clause should not render .orderBy(id) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); List animals = mapper.selectMany(selectStatement); diff --git a/src/test/java/examples/complexquery/ComplexQueryTest.java b/src/test/java/examples/complexquery/ComplexQueryTest.java index 28543469c..aef9b9196 100644 --- a/src/test/java/examples/complexquery/ComplexQueryTest.java +++ b/src/test/java/examples/complexquery/ComplexQueryTest.java @@ -110,7 +110,8 @@ void testAllNull() { SelectStatementProvider search(Integer targetId, String fName, String lName) { QueryExpressionDSL.QueryExpressionWhereBuilder builder = select(id, firstName, lastName) .from(person) - .where(); + .where() + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)); if (targetId != null) { builder diff --git a/src/test/java/examples/emptywhere/EmptyWhereTest.java b/src/test/java/examples/emptywhere/EmptyWhereTest.java index 3bbe41d86..8f03a6d45 100644 --- a/src/test/java/examples/emptywhere/EmptyWhereTest.java +++ b/src/test/java/examples/emptywhere/EmptyWhereTest.java @@ -119,6 +119,7 @@ void testDeleteVariations(Variation variation) { builder.and(firstName, isEqualTo(variation.firstName).filter(Objects::nonNull)); builder.or(PersonDynamicSqlSupport.lastName, isEqualTo(variation.lastName).filter(Objects::nonNull)); + builder.configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)); DeleteStatementProvider deleteStatement = builder.build().render(RenderingStrategies.MYBATIS3); @@ -159,6 +160,7 @@ void testSelectVariations(Variation variation) { builder.and(firstName, isEqualTo(variation.firstName).filter(Objects::nonNull)); builder.or(PersonDynamicSqlSupport.lastName, isEqualTo(variation.lastName).filter(Objects::nonNull)); + builder.configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)); SelectStatementProvider selectStatement = builder.build().render(RenderingStrategies.MYBATIS3); @@ -200,6 +202,7 @@ void testJoinVariations(Variation variation) { builder.and(firstName, isEqualTo(variation.firstName).filter(Objects::nonNull)); builder.or(PersonDynamicSqlSupport.lastName, isEqualTo(variation.lastName).filter(Objects::nonNull)); + builder.configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)); SelectStatementProvider selectStatement = builder.build().render(RenderingStrategies.MYBATIS3); @@ -243,6 +246,7 @@ void testUpdateVariations(Variation variation) { builder.and(firstName, isEqualTo(variation.firstName).filter(Objects::nonNull)); builder.or(PersonDynamicSqlSupport.lastName, isEqualTo(variation.lastName).filter(Objects::nonNull)); + builder.configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)); UpdateStatementProvider updateStatement = builder.build().render(RenderingStrategies.MYBATIS3); @@ -279,6 +283,7 @@ void testWhereVariations(Variation variation) { builder.and(firstName, isEqualTo(variation.firstName).filter(Objects::nonNull)); builder.or(PersonDynamicSqlSupport.lastName, isEqualTo(variation.lastName).filter(Objects::nonNull)); + builder.configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)); WhereClauseProvider whereClause = builder.build().render(RenderingStrategies.MYBATIS3); diff --git a/src/test/java/examples/joins/JoinMapperTest.java b/src/test/java/examples/joins/JoinMapperTest.java index d22203b1e..b97edab09 100644 --- a/src/test/java/examples/joins/JoinMapperTest.java +++ b/src/test/java/examples/joins/JoinMapperTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2021 the original author or authors. + * Copyright 2016-2022 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. diff --git a/src/test/java/issues/gh105/Issue105Test.java b/src/test/java/issues/gh105/Issue105Test.java index 7d4aa99df..7608553cf 100644 --- a/src/test/java/issues/gh105/Issue105Test.java +++ b/src/test/java/issues/gh105/Issue105Test.java @@ -99,6 +99,7 @@ void testFuzzyLikeBothNull() { .from(person) .where(firstName, isLike(fName).filter(Objects::nonNull).map(SearchUtils::addWildcards)) .and(lastName, isLike(lName).filter(Objects::nonNull).map(SearchUtils::addWildcards)) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -527,6 +528,7 @@ void testBetweenTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(age, isBetween(1).and((Integer) null).filter(Predicates.bothPresent()).map(i1 -> i1 + 1, i2 -> i2 + 2)) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -542,6 +544,7 @@ void testBetweenWhenPresentTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(age, isBetweenWhenPresent(1).and((Integer) null).map(i1 -> i1 + 1, i2 -> i2 + 2)) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -557,6 +560,7 @@ void testEqualTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(age, isEqualTo((Integer) null).filter(Objects::nonNull).map(i -> i + 1)) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -572,6 +576,7 @@ void testEqualWhenPresentTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(age, isEqualToWhenPresent((Integer) null).map(i -> i + 1)) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -587,6 +592,7 @@ void testGreaterThanTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(age, isGreaterThan((Integer) null).filter(Objects::nonNull).map(i -> i + 1)) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -602,6 +608,7 @@ void testGreaterThanOrEqualTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(age, isGreaterThanOrEqualTo((Integer) null).filter(Objects::nonNull).map(i -> i + 1)) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -617,6 +624,7 @@ void testGreaterThanOrEqualWhenPresentTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(age, isGreaterThanOrEqualToWhenPresent((Integer) null).map(i -> i + 1)) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -632,6 +640,7 @@ void testGreaterThanWhenPresentTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(age, isGreaterThanWhenPresent((Integer) null).map(i -> i + 1)) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -647,6 +656,7 @@ void testLessThanTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(age, isLessThan((Integer) null).filter(Objects::nonNull).map(i -> i + 1)) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -662,6 +672,7 @@ void testLessThanOrEqualTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(age, isLessThanOrEqualTo((Integer) null).filter(Objects::nonNull).map(i -> i + 1)) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -677,6 +688,7 @@ void testLessThanOrEqualWhenPresentTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(age, isLessThanOrEqualToWhenPresent((Integer) null).map(i -> i + 1)) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -692,6 +704,7 @@ void testLessThanWhenPresentTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(age, isLessThanWhenPresent((Integer) null).map(i -> i + 1)) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -707,6 +720,7 @@ void testLikeTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(firstName, isLike((String) null).filter(Objects::nonNull).map(SearchUtils::addWildcards)) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -722,6 +736,7 @@ void testLikeCaseInsensitiveTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(firstName, isLikeCaseInsensitive((String) null).filter(Objects::nonNull).map(SearchUtils::addWildcards)) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -737,6 +752,7 @@ void testLikeCaseInsensitiveWhenPresentTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(firstName, isLikeCaseInsensitiveWhenPresent((String) null).map(SearchUtils::addWildcards)) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -752,6 +768,7 @@ void testLikeWhenPresentTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(firstName, isLikeWhenPresent((String) null).map(SearchUtils::addWildcards)) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -767,6 +784,7 @@ void testNotBetweenTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(age, isNotBetween((Integer) null).and(10).filter(Predicates.bothPresent()).map(i1 -> i1 + 1, i2 -> i2 + 2)) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -782,6 +800,7 @@ void testNotBetweenWhenPresentTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(age, isNotBetweenWhenPresent(1).and((Integer) null).map(i1 -> i1 + 1, i2 -> i2 + 2)) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -797,6 +816,7 @@ void testNotEqualTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(age, isNotEqualTo((Integer) null).filter(Objects::nonNull).map(i -> i + 1)) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -812,6 +832,7 @@ void testNotEqualWhenPresentTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(age, isNotEqualToWhenPresent((Integer) null).map(i -> i + 1)) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -827,6 +848,7 @@ void testNotLikeTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(firstName, isNotLike((String) null).filter(Objects::nonNull).map(SearchUtils::addWildcards)) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -842,6 +864,7 @@ void testNotLikeCaseInsensitiveTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(firstName, isNotLikeCaseInsensitive((String) null).filter(Objects::nonNull).map(SearchUtils::addWildcards)) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -857,6 +880,7 @@ void testNotLikeCaseInsensitiveWhenPresentTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(firstName, isNotLikeCaseInsensitiveWhenPresent((String) null).map(SearchUtils::addWildcards)) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -872,6 +896,7 @@ void testNotLikeWhenPresentTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(firstName, isNotLikeWhenPresent((String) null).map(SearchUtils::addWildcards)) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); diff --git a/src/test/java/org/mybatis/dynamic/sql/select/SelectStatementTest.java b/src/test/java/org/mybatis/dynamic/sql/select/SelectStatementTest.java index 571caf9a8..43920fc95 100644 --- a/src/test/java/org/mybatis/dynamic/sql/select/SelectStatementTest.java +++ b/src/test/java/org/mybatis/dynamic/sql/select/SelectStatementTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2021 the original author or authors. + * Copyright 2016-2022 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. @@ -398,6 +398,7 @@ void testInWhenPresentNullList() { SelectStatementProvider selectStatement = select(column1, column3) .from(table) .where(column3, isInWhenPresent((Collection) null)) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -409,6 +410,7 @@ void testInCaseInsensitiveWhenPresentNullList() { SelectStatementProvider selectStatement = select(column1, column3) .from(table) .where(column3, isInCaseInsensitiveWhenPresent((Collection) null)) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -420,6 +422,7 @@ void testNotInWhenPresentNullList() { SelectStatementProvider selectStatement = select(column1, column3) .from(table) .where(column3, isNotInWhenPresent((Collection) null)) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -431,6 +434,7 @@ void testNotInCaseInsensitiveWhenPresentNullList() { SelectStatementProvider selectStatement = select(column1, column3) .from(table) .where(column3, isNotInCaseInsensitiveWhenPresent((Collection) null)) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); diff --git a/src/test/java/org/mybatis/dynamic/sql/where/render/OptionalCriterionRenderTest.java b/src/test/java/org/mybatis/dynamic/sql/where/render/OptionalCriterionRenderTest.java index 00cf36dd6..7b0cd2821 100644 --- a/src/test/java/org/mybatis/dynamic/sql/where/render/OptionalCriterionRenderTest.java +++ b/src/test/java/org/mybatis/dynamic/sql/where/render/OptionalCriterionRenderTest.java @@ -38,6 +38,7 @@ void testNoRenderableCriteria() { Integer nullId = null; WhereClauseProvider whereClause = where(id, isEqualToWhenPresent(nullId)) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.SPRING_NAMED_PARAMETER); @@ -52,6 +53,7 @@ void testNoRenderableCriteriaWithIf() { Integer nullId = null; WhereClauseProvider whereClause = where(id, isEqualTo(nullId).filter(Objects::nonNull)) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.SPRING_NAMED_PARAMETER); @@ -64,6 +66,7 @@ void testNoRenderableCriteriaWithIf() { @Test void testDisabledIsNull() { WhereClauseProvider whereClause = where(id, isNull().filter(() -> false)) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.SPRING_NAMED_PARAMETER); @@ -88,6 +91,7 @@ void testEnabledIsNull() { @Test void testDisabledIsNotNull() { WhereClauseProvider whereClause = where(id, isNotNull().filter(() -> false)) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.SPRING_NAMED_PARAMETER); @@ -308,6 +312,7 @@ void testCollapsingCriteriaGroup1() { WhereClauseProvider whereClause = where( group(firstName, isEqualToWhenPresent(name1)), or(lastName, isEqualToWhenPresent(name1))) + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) .build() .render(RenderingStrategies.SPRING_NAMED_PARAMETER); diff --git a/src/test/kotlin/examples/kotlin/spring/canonical/InfixElementsTest.kt b/src/test/kotlin/examples/kotlin/spring/canonical/InfixElementsTest.kt index d0b144ef6..2bba78fee 100644 --- a/src/test/kotlin/examples/kotlin/spring/canonical/InfixElementsTest.kt +++ b/src/test/kotlin/examples/kotlin/spring/canonical/InfixElementsTest.kt @@ -24,10 +24,13 @@ import examples.kotlin.spring.canonical.PersonDynamicSqlSupport.lastName import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThatExceptionOfType import org.junit.jupiter.api.Test +import org.mybatis.dynamic.sql.exception.UnrenderableWhereClauseException import org.mybatis.dynamic.sql.util.kotlin.KInvalidSQLException import org.mybatis.dynamic.sql.util.kotlin.elements.isLike import org.mybatis.dynamic.sql.util.kotlin.elements.stringConstant import org.mybatis.dynamic.sql.util.kotlin.elements.upper +import org.mybatis.dynamic.sql.util.kotlin.spring.delete +import org.mybatis.dynamic.sql.util.kotlin.spring.deleteFrom import org.mybatis.dynamic.sql.util.kotlin.spring.select import org.mybatis.dynamic.sql.util.kotlin.spring.selectList import org.mybatis.dynamic.sql.util.kotlin.spring.selectOne @@ -37,7 +40,7 @@ import org.springframework.test.context.junit.jupiter.SpringJUnitConfig import org.springframework.transaction.annotation.Transactional @Suppress("LargeClass") -@SpringJUnitConfig(classes = [SpringConfiguration::class]) +@SpringJUnitConfig(SpringConfiguration::class) @Transactional open class InfixElementsTest { @Autowired @@ -93,12 +96,24 @@ open class InfixElementsTest { assertThat(rows[0]).isEqualTo("Bamm Bamm") } + @Test + fun testVanishingWhereClause() { + assertThatExceptionOfType(UnrenderableWhereClauseException::class.java).isThrownBy { + select(firstName) { + from(person) + where { id isEqualToWhenPresent null } + orderBy(id) + } + } + } + @Test fun testIsEqualToWhenPresentNull() { val selectStatement = select(firstName) { from(person) where { id isEqualToWhenPresent null } orderBy(id) + configureStatement { unrenderableWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -129,12 +144,29 @@ open class InfixElementsTest { assertThat(rows[0]).isEqualTo("Fred") } + @Test + fun testDeleteIsNotEqualToWhenPresentNull() { + val deleteStatement = deleteFrom(person) { + where { id isNotEqualToWhenPresent null } + configureStatement { unrenderableWhereClauseAllowed = true } + } + + assertThat(deleteStatement.deleteStatement).isEqualTo( + "delete from Person" + ) + + val rows = template.delete(deleteStatement) + + assertThat(rows).isEqualTo(6) + } + @Test fun testIsNotEqualToWhenPresentNull() { val selectStatement = select(firstName) { from(person) where { id isNotEqualToWhenPresent null } orderBy(id) + configureStatement { unrenderableWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -171,6 +203,7 @@ open class InfixElementsTest { from(person) where { id isGreaterThanWhenPresent null } orderBy(id) + configureStatement { unrenderableWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -207,6 +240,7 @@ open class InfixElementsTest { from(person) where { id isGreaterThanOrEqualToWhenPresent null } orderBy(id) + configureStatement { unrenderableWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -243,6 +277,7 @@ open class InfixElementsTest { from(person) where { id isGreaterThanWhenPresent null } orderBy(id) + configureStatement { unrenderableWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -297,6 +332,7 @@ open class InfixElementsTest { from(person) where { id isLessThanOrEqualToWhenPresent null } orderBy(id) + configureStatement { unrenderableWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -465,6 +501,7 @@ open class InfixElementsTest { from(person) where { id isBetweenWhenPresent null and 3 } orderBy(id) + configureStatement { unrenderableWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -483,6 +520,7 @@ open class InfixElementsTest { from(person) where { id isBetweenWhenPresent 2 and null } orderBy(id) + configureStatement { unrenderableWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -501,6 +539,7 @@ open class InfixElementsTest { from(person) where { id isBetweenWhenPresent null and null } orderBy(id) + configureStatement { unrenderableWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -555,6 +594,7 @@ open class InfixElementsTest { from(person) where { id isNotBetweenWhenPresent null and 3 } orderBy(id) + configureStatement { unrenderableWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -573,6 +613,7 @@ open class InfixElementsTest { from(person) where { id isNotBetweenWhenPresent 2 and null } orderBy(id) + configureStatement { unrenderableWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -591,6 +632,7 @@ open class InfixElementsTest { from(person) where { id isNotBetweenWhenPresent null and null } orderBy(id) + configureStatement { unrenderableWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -627,6 +669,7 @@ open class InfixElementsTest { from(person) where { firstName isLikeWhenPresent null } orderBy(id) + configureStatement { unrenderableWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -681,6 +724,7 @@ open class InfixElementsTest { from(person) where { firstName isNotLikeWhenPresent null } orderBy(id) + configureStatement { unrenderableWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -735,6 +779,7 @@ open class InfixElementsTest { from(person) where { firstName isLikeCaseInsensitiveWhenPresent null } orderBy(id) + configureStatement { unrenderableWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -789,6 +834,7 @@ open class InfixElementsTest { from(person) where { firstName isNotLikeCaseInsensitiveWhenPresent null } orderBy(id) + configureStatement { unrenderableWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -843,6 +889,7 @@ open class InfixElementsTest { from(person) where { firstName.isInCaseInsensitiveWhenPresent(null, null) } orderBy(id) + configureStatement { unrenderableWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -897,6 +944,7 @@ open class InfixElementsTest { from(person) where { firstName.isNotInCaseInsensitiveWhenPresent(null, null) } orderBy(id) + configureStatement { unrenderableWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -922,6 +970,7 @@ open class InfixElementsTest { .map { "%$it%" }) } orderBy(id) + configureStatement { unrenderableWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( diff --git a/src/test/kotlin/examples/kotlin/spring/canonical/KotlinElementsTest.kt b/src/test/kotlin/examples/kotlin/spring/canonical/KotlinElementsTest.kt index bd6cb3d4a..24ced760f 100644 --- a/src/test/kotlin/examples/kotlin/spring/canonical/KotlinElementsTest.kt +++ b/src/test/kotlin/examples/kotlin/spring/canonical/KotlinElementsTest.kt @@ -57,7 +57,7 @@ import org.springframework.test.context.junit.jupiter.SpringJUnitConfig import org.springframework.transaction.annotation.Transactional @Suppress("LargeClass", "MaxLineLength") -@SpringJUnitConfig(classes = [SpringConfiguration::class]) +@SpringJUnitConfig(SpringConfiguration::class) @Transactional open class KotlinElementsTest { @Autowired @@ -335,6 +335,7 @@ open class KotlinElementsTest { from(person) where { id (isBetweenWhenPresent(null).and(3)) } orderBy(id) + configureStatement { unrenderableWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -353,6 +354,7 @@ open class KotlinElementsTest { from(person) where { id (isBetweenWhenPresent(2).and(null)) } orderBy(id) + configureStatement { unrenderableWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -371,6 +373,7 @@ open class KotlinElementsTest { from(person) where { id (isBetweenWhenPresent(null).and(null)) } orderBy(id) + configureStatement { unrenderableWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -425,6 +428,7 @@ open class KotlinElementsTest { from(person) where { id (isNotBetweenWhenPresent(null).and(3)) } orderBy(id) + configureStatement { unrenderableWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -443,6 +447,7 @@ open class KotlinElementsTest { from(person) where { id (isNotBetweenWhenPresent(2).and(null)) } orderBy(id) + configureStatement { unrenderableWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -461,6 +466,7 @@ open class KotlinElementsTest { from(person) where { id (isNotBetweenWhenPresent(null).and(null)) } orderBy(id) + configureStatement { unrenderableWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -551,6 +557,7 @@ open class KotlinElementsTest { from(person) where { firstName (isInCaseInsensitiveWhenPresent(null, null)) } orderBy(id) + configureStatement { unrenderableWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -605,6 +612,7 @@ open class KotlinElementsTest { from(person) where { firstName (isNotInCaseInsensitiveWhenPresent(null, null)) } orderBy(id) + configureStatement { unrenderableWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( From 11aa4c8bd1577cab211c3fcafdfe698fb78e52c2 Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Mon, 15 Aug 2022 09:37:23 -0400 Subject: [PATCH 03/23] Move configuration classes into a new package --- .../sql/{ => configuration}/GlobalConfiguration.java | 2 +- .../sql/{ => configuration}/StatementConfiguration.java | 2 +- .../java/org/mybatis/dynamic/sql/delete/DeleteDSL.java | 2 +- .../sql/exception/UnrenderableWhereClauseException.java | 7 +++++-- src/main/java/org/mybatis/dynamic/sql/select/CountDSL.java | 2 +- .../org/mybatis/dynamic/sql/select/QueryExpressionDSL.java | 2 +- .../java/org/mybatis/dynamic/sql/select/SelectDSL.java | 2 +- .../java/org/mybatis/dynamic/sql/update/UpdateDSL.java | 2 +- .../mybatis/dynamic/sql/util/ConfigurableStatement.java | 2 +- .../org/mybatis/dynamic/sql/where/AbstractWhereDSL.java | 2 +- src/main/java/org/mybatis/dynamic/sql/where/WhereDSL.java | 2 +- .../java/org/mybatis/dynamic/sql/where/WhereModel.java | 2 +- .../mybatis/dynamic/sql/util/kotlin/KotlinBaseBuilders.kt | 2 +- 13 files changed, 17 insertions(+), 14 deletions(-) rename src/main/java/org/mybatis/dynamic/sql/{ => configuration}/GlobalConfiguration.java (97%) rename src/main/java/org/mybatis/dynamic/sql/{ => configuration}/StatementConfiguration.java (97%) diff --git a/src/main/java/org/mybatis/dynamic/sql/GlobalConfiguration.java b/src/main/java/org/mybatis/dynamic/sql/configuration/GlobalConfiguration.java similarity index 97% rename from src/main/java/org/mybatis/dynamic/sql/GlobalConfiguration.java rename to src/main/java/org/mybatis/dynamic/sql/configuration/GlobalConfiguration.java index 26bc2f327..ee3ec16d7 100644 --- a/src/main/java/org/mybatis/dynamic/sql/GlobalConfiguration.java +++ b/src/main/java/org/mybatis/dynamic/sql/configuration/GlobalConfiguration.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.mybatis.dynamic.sql; +package org.mybatis.dynamic.sql.configuration; import java.io.IOException; import java.io.InputStream; diff --git a/src/main/java/org/mybatis/dynamic/sql/StatementConfiguration.java b/src/main/java/org/mybatis/dynamic/sql/configuration/StatementConfiguration.java similarity index 97% rename from src/main/java/org/mybatis/dynamic/sql/StatementConfiguration.java rename to src/main/java/org/mybatis/dynamic/sql/configuration/StatementConfiguration.java index db9e09b08..0a217a20c 100644 --- a/src/main/java/org/mybatis/dynamic/sql/StatementConfiguration.java +++ b/src/main/java/org/mybatis/dynamic/sql/configuration/StatementConfiguration.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.mybatis.dynamic.sql; +package org.mybatis.dynamic.sql.configuration; /** * This class can be used to change some behaviors of the framework. Every configurable statement diff --git a/src/main/java/org/mybatis/dynamic/sql/delete/DeleteDSL.java b/src/main/java/org/mybatis/dynamic/sql/delete/DeleteDSL.java index d47c1f25b..2a27b452d 100644 --- a/src/main/java/org/mybatis/dynamic/sql/delete/DeleteDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/delete/DeleteDSL.java @@ -20,7 +20,7 @@ import org.jetbrains.annotations.NotNull; import org.mybatis.dynamic.sql.SqlTable; -import org.mybatis.dynamic.sql.StatementConfiguration; +import org.mybatis.dynamic.sql.configuration.StatementConfiguration; import org.mybatis.dynamic.sql.util.Buildable; import org.mybatis.dynamic.sql.where.AbstractWhereDSL; import org.mybatis.dynamic.sql.where.AbstractWhereSupport; diff --git a/src/main/java/org/mybatis/dynamic/sql/exception/UnrenderableWhereClauseException.java b/src/main/java/org/mybatis/dynamic/sql/exception/UnrenderableWhereClauseException.java index 0c4b925d3..f68e3afb2 100644 --- a/src/main/java/org/mybatis/dynamic/sql/exception/UnrenderableWhereClauseException.java +++ b/src/main/java/org/mybatis/dynamic/sql/exception/UnrenderableWhereClauseException.java @@ -15,6 +15,9 @@ */ package org.mybatis.dynamic.sql.exception; +import org.mybatis.dynamic.sql.configuration.GlobalConfiguration; +import org.mybatis.dynamic.sql.configuration.StatementConfiguration; + /** * This exception is thrown when the where clause in a statement will not render. * This can happen if all the optional conditions in a where clause fail to @@ -28,8 +31,8 @@ * If you intend to allow an unrenderable where clause, then configure the * statement to allow it, or change the global configuration. * - * @see org.mybatis.dynamic.sql.GlobalConfiguration - * @see org.mybatis.dynamic.sql.StatementConfiguration + * @see GlobalConfiguration + * @see StatementConfiguration * @since 1.4.1 * @author Jeff Butler */ diff --git a/src/main/java/org/mybatis/dynamic/sql/select/CountDSL.java b/src/main/java/org/mybatis/dynamic/sql/select/CountDSL.java index 8a87a12bc..b11fe5d01 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/CountDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/CountDSL.java @@ -22,7 +22,7 @@ import org.mybatis.dynamic.sql.BasicColumn; import org.mybatis.dynamic.sql.SqlBuilder; import org.mybatis.dynamic.sql.SqlTable; -import org.mybatis.dynamic.sql.StatementConfiguration; +import org.mybatis.dynamic.sql.configuration.StatementConfiguration; import org.mybatis.dynamic.sql.util.Buildable; import org.mybatis.dynamic.sql.where.AbstractWhereDSL; import org.mybatis.dynamic.sql.where.WhereModel; diff --git a/src/main/java/org/mybatis/dynamic/sql/select/QueryExpressionDSL.java b/src/main/java/org/mybatis/dynamic/sql/select/QueryExpressionDSL.java index e462ee6d6..d8e134a85 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/QueryExpressionDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/QueryExpressionDSL.java @@ -26,8 +26,8 @@ import org.mybatis.dynamic.sql.BasicColumn; import org.mybatis.dynamic.sql.SortSpecification; import org.mybatis.dynamic.sql.SqlTable; -import org.mybatis.dynamic.sql.StatementConfiguration; import org.mybatis.dynamic.sql.TableExpression; +import org.mybatis.dynamic.sql.configuration.StatementConfiguration; import org.mybatis.dynamic.sql.select.join.JoinCondition; import org.mybatis.dynamic.sql.select.join.JoinCriterion; import org.mybatis.dynamic.sql.select.join.JoinSpecification; 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 cc4088e29..c5b850ab7 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/SelectDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/SelectDSL.java @@ -28,8 +28,8 @@ import org.mybatis.dynamic.sql.BasicColumn; import org.mybatis.dynamic.sql.SortSpecification; import org.mybatis.dynamic.sql.SqlTable; -import org.mybatis.dynamic.sql.StatementConfiguration; import org.mybatis.dynamic.sql.TableExpression; +import org.mybatis.dynamic.sql.configuration.StatementConfiguration; import org.mybatis.dynamic.sql.select.QueryExpressionDSL.FromGatherer; import org.mybatis.dynamic.sql.util.Buildable; import org.mybatis.dynamic.sql.util.ConfigurableStatement; diff --git a/src/main/java/org/mybatis/dynamic/sql/update/UpdateDSL.java b/src/main/java/org/mybatis/dynamic/sql/update/UpdateDSL.java index 622038b04..378afdd29 100644 --- a/src/main/java/org/mybatis/dynamic/sql/update/UpdateDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/update/UpdateDSL.java @@ -25,7 +25,7 @@ import org.mybatis.dynamic.sql.BasicColumn; import org.mybatis.dynamic.sql.SqlColumn; import org.mybatis.dynamic.sql.SqlTable; -import org.mybatis.dynamic.sql.StatementConfiguration; +import org.mybatis.dynamic.sql.configuration.StatementConfiguration; import org.mybatis.dynamic.sql.select.SelectModel; import org.mybatis.dynamic.sql.util.AbstractColumnMapping; import org.mybatis.dynamic.sql.util.Buildable; diff --git a/src/main/java/org/mybatis/dynamic/sql/util/ConfigurableStatement.java b/src/main/java/org/mybatis/dynamic/sql/util/ConfigurableStatement.java index c723c06a7..c6a86a135 100644 --- a/src/main/java/org/mybatis/dynamic/sql/util/ConfigurableStatement.java +++ b/src/main/java/org/mybatis/dynamic/sql/util/ConfigurableStatement.java @@ -15,7 +15,7 @@ */ package org.mybatis.dynamic.sql.util; -import org.mybatis.dynamic.sql.StatementConfiguration; +import org.mybatis.dynamic.sql.configuration.StatementConfiguration; import java.util.function.Consumer; diff --git a/src/main/java/org/mybatis/dynamic/sql/where/AbstractWhereDSL.java b/src/main/java/org/mybatis/dynamic/sql/where/AbstractWhereDSL.java index 950851aa6..85d424ca1 100644 --- a/src/main/java/org/mybatis/dynamic/sql/where/AbstractWhereDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/where/AbstractWhereDSL.java @@ -29,8 +29,8 @@ import org.mybatis.dynamic.sql.ExistsCriterion; import org.mybatis.dynamic.sql.ExistsPredicate; import org.mybatis.dynamic.sql.SqlCriterion; -import org.mybatis.dynamic.sql.StatementConfiguration; import org.mybatis.dynamic.sql.VisitableCondition; +import org.mybatis.dynamic.sql.configuration.StatementConfiguration; import org.mybatis.dynamic.sql.util.ConfigurableStatement; public abstract class AbstractWhereDSL> implements ConfigurableStatement { diff --git a/src/main/java/org/mybatis/dynamic/sql/where/WhereDSL.java b/src/main/java/org/mybatis/dynamic/sql/where/WhereDSL.java index 7d09346c5..f9563c35c 100644 --- a/src/main/java/org/mybatis/dynamic/sql/where/WhereDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/where/WhereDSL.java @@ -15,7 +15,7 @@ */ package org.mybatis.dynamic.sql.where; -import org.mybatis.dynamic.sql.StatementConfiguration; +import org.mybatis.dynamic.sql.configuration.StatementConfiguration; public class WhereDSL extends AbstractWhereDSL { private WhereDSL() { diff --git a/src/main/java/org/mybatis/dynamic/sql/where/WhereModel.java b/src/main/java/org/mybatis/dynamic/sql/where/WhereModel.java index a0b01c4c4..0d2b5db97 100644 --- a/src/main/java/org/mybatis/dynamic/sql/where/WhereModel.java +++ b/src/main/java/org/mybatis/dynamic/sql/where/WhereModel.java @@ -24,7 +24,7 @@ import org.mybatis.dynamic.sql.AndOrCriteriaGroup; import org.mybatis.dynamic.sql.SqlCriterion; -import org.mybatis.dynamic.sql.StatementConfiguration; +import org.mybatis.dynamic.sql.configuration.StatementConfiguration; import org.mybatis.dynamic.sql.render.RenderingStrategy; import org.mybatis.dynamic.sql.render.TableAliasCalculator; import org.mybatis.dynamic.sql.where.render.WhereClauseProvider; diff --git a/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/KotlinBaseBuilders.kt b/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/KotlinBaseBuilders.kt index 375af1bcc..fe868ac75 100644 --- a/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/KotlinBaseBuilders.kt +++ b/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/KotlinBaseBuilders.kt @@ -19,8 +19,8 @@ import org.mybatis.dynamic.sql.BindableColumn import org.mybatis.dynamic.sql.AndOrCriteriaGroup import org.mybatis.dynamic.sql.ExistsPredicate import org.mybatis.dynamic.sql.SqlTable -import org.mybatis.dynamic.sql.StatementConfiguration import org.mybatis.dynamic.sql.VisitableCondition +import org.mybatis.dynamic.sql.configuration.StatementConfiguration import org.mybatis.dynamic.sql.select.AbstractQueryExpressionDSL import org.mybatis.dynamic.sql.where.AbstractWhereDSL import org.mybatis.dynamic.sql.where.AbstractWhereSupport From 6e537cf8b48870756b6c162e385b612fe54e52d0 Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Tue, 16 Aug 2022 11:12:47 -0400 Subject: [PATCH 04/23] Better docs --- .../sql/configuration/StatementConfiguration.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/mybatis/dynamic/sql/configuration/StatementConfiguration.java b/src/main/java/org/mybatis/dynamic/sql/configuration/StatementConfiguration.java index 0a217a20c..be98f417b 100644 --- a/src/main/java/org/mybatis/dynamic/sql/configuration/StatementConfiguration.java +++ b/src/main/java/org/mybatis/dynamic/sql/configuration/StatementConfiguration.java @@ -15,19 +15,23 @@ */ package org.mybatis.dynamic.sql.configuration; +import org.mybatis.dynamic.sql.exception.UnrenderableWhereClauseException; + /** * This class can be used to change some behaviors of the framework. Every configurable statement * contains a unique instance of this class, so changes here will only impact a single statement. - * If you intend to change the behavior for all statements, use the {@link GlobalConfiguration} - * configuration class. + * If you intend to change the behavior for all statements, use the {@link GlobalConfiguration}. + * Initial values for this class in each statement are set from the {@link GlobalConfiguration}. + * Configurable behaviors are detailed below: * *

*
unrenderableWhereClauseAllowed
*
If false (default), the framework will throw an - * {@link org.mybatis.dynamic.sql.exception.UnrenderableWhereClauseException} + * {@link UnrenderableWhereClauseException} * if a where clause is specified in the statement, but it fails to render because all * optional conditions do not render. For example, if an "in" condition specifies an - * empty list of values. + * empty list of values. If no criteria are specified in a where clause, the framework + * assumes that no where clause was intended and will not throw an exception. *
*
* From d656b15a320196188088508a8d249f7d148d059d Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Tue, 16 Aug 2022 15:51:25 -0400 Subject: [PATCH 05/23] Checkstyle --- .../org/mybatis/dynamic/sql/BasicColumn.java | 4 +- .../org/mybatis/dynamic/sql/SqlBuilder.java | 50 +++++++++---------- .../configuration/GlobalConfiguration.java | 2 +- .../UnrenderableWhereClauseException.java | 8 +-- .../dynamic/sql/insert/BatchInsertDSL.java | 2 +- .../dynamic/sql/insert/InsertSelectDSL.java | 4 +- .../dynamic/sql/insert/MultiRowInsertDSL.java | 2 +- .../select/AbstractQueryExpressionDSL.java | 18 +++---- .../sql/select/QueryExpressionDSL.java | 22 ++++---- .../mybatis/dynamic/sql/select/SelectDSL.java | 8 +-- .../sql/select/SelectDSLCompleter.java | 4 +- .../sql/util/ConfigurableStatement.java | 4 +- .../util/springbatch/SpringBatchUtility.java | 6 +-- .../dynamic/sql/where/AbstractWhereDSL.java | 18 +++---- .../sql/where/AbstractWhereSupport.java | 6 +-- 15 files changed, 79 insertions(+), 79 deletions(-) diff --git a/src/main/java/org/mybatis/dynamic/sql/BasicColumn.java b/src/main/java/org/mybatis/dynamic/sql/BasicColumn.java index 0764c1904..c3aff7b6d 100644 --- a/src/main/java/org/mybatis/dynamic/sql/BasicColumn.java +++ b/src/main/java/org/mybatis/dynamic/sql/BasicColumn.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2022 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. @@ -74,7 +74,7 @@ default String renderWithTableAndColumnAlias(TableAliasCalculator tableAliasCalc * @param columns list of BasicColumn * @return an array of BasicColumn */ - static BasicColumn[] columnList(BasicColumn...columns) { + static BasicColumn[] columnList(BasicColumn... columns) { return columns; } } diff --git a/src/main/java/org/mybatis/dynamic/sql/SqlBuilder.java b/src/main/java/org/mybatis/dynamic/sql/SqlBuilder.java index 42aa8eaee..09bc4368a 100644 --- a/src/main/java/org/mybatis/dynamic/sql/SqlBuilder.java +++ b/src/main/java/org/mybatis/dynamic/sql/SqlBuilder.java @@ -144,7 +144,7 @@ static InsertDSL.IntoGatherer insert(T row) { * @return the next step in the DSL */ @SafeVarargs - static BatchInsertDSL.IntoGatherer insertBatch(T...records) { + static BatchInsertDSL.IntoGatherer insertBatch(T... records) { return BatchInsertDSL.insert(records); } @@ -171,7 +171,7 @@ static BatchInsertDSL.IntoGatherer insertBatch(Collection records) { * @return the next step in the DSL */ @SafeVarargs - static MultiRowInsertDSL.IntoGatherer insertMultiple(T...records) { + static MultiRowInsertDSL.IntoGatherer insertMultiple(T... records) { return MultiRowInsertDSL.insert(records); } @@ -194,7 +194,7 @@ static InsertIntoNextStep insertInto(SqlTable table) { return new InsertIntoNextStep(table); } - static FromGatherer select(BasicColumn...selectList) { + static FromGatherer select(BasicColumn... selectList) { return SelectDSL.select(selectList); } @@ -202,7 +202,7 @@ static FromGatherer select(Collection selectList) { return SelectDSL.select(selectList); } - static FromGatherer selectDistinct(BasicColumn...selectList) { + static FromGatherer selectDistinct(BasicColumn... selectList) { return SelectDSL.selectDistinct(selectList); } @@ -237,7 +237,7 @@ static WhereDSL where(ExistsPredicate existsPredicate, AndOrCriteriaGroup... sub // where condition connectors static CriteriaGroup group(BindableColumn column, VisitableCondition condition, - AndOrCriteriaGroup...subCriteria) { + AndOrCriteriaGroup... subCriteria) { return group(column, condition, Arrays.asList(subCriteria)); } @@ -250,7 +250,7 @@ static CriteriaGroup group(BindableColumn column, VisitableCondition c .build(); } - static CriteriaGroup group(ExistsPredicate existsPredicate, AndOrCriteriaGroup...subCriteria) { + static CriteriaGroup group(ExistsPredicate existsPredicate, AndOrCriteriaGroup... subCriteria) { return group(existsPredicate, Arrays.asList(subCriteria)); } @@ -262,7 +262,7 @@ static CriteriaGroup group(ExistsPredicate existsPredicate, List subCriteria) { } static NotCriterion not(BindableColumn column, VisitableCondition condition, - AndOrCriteriaGroup...subCriteria) { + AndOrCriteriaGroup... subCriteria) { return not(column, condition, Arrays.asList(subCriteria)); } @@ -293,7 +293,7 @@ static NotCriterion not(BindableColumn column, VisitableCondition cond .build(); } - static NotCriterion not(ExistsPredicate existsPredicate, AndOrCriteriaGroup...subCriteria) { + static NotCriterion not(ExistsPredicate existsPredicate, AndOrCriteriaGroup... subCriteria) { return not(existsPredicate, Arrays.asList(subCriteria)); } @@ -305,7 +305,7 @@ static NotCriterion not(ExistsPredicate existsPredicate, List subCriteria) { } static AndOrCriteriaGroup or(BindableColumn column, VisitableCondition condition, - AndOrCriteriaGroup...subCriteria) { + AndOrCriteriaGroup... subCriteria) { return new AndOrCriteriaGroup.Builder() .withInitialCriterion(ColumnAndConditionCriterion.withColumn(column) .withCondition(condition) @@ -333,7 +333,7 @@ static AndOrCriteriaGroup or(BindableColumn column, VisitableCondition .build(); } - static AndOrCriteriaGroup or(ExistsPredicate existsPredicate, AndOrCriteriaGroup...subCriteria) { + static AndOrCriteriaGroup or(ExistsPredicate existsPredicate, AndOrCriteriaGroup... subCriteria) { return new AndOrCriteriaGroup.Builder() .withInitialCriterion(new ExistsCriterion.Builder() .withExistsPredicate(existsPredicate).build()) @@ -342,7 +342,7 @@ static AndOrCriteriaGroup or(ExistsPredicate existsPredicate, AndOrCriteriaGroup .build(); } - static AndOrCriteriaGroup or(SqlCriterion initialCriterion, AndOrCriteriaGroup...subCriteria) { + static AndOrCriteriaGroup or(SqlCriterion initialCriterion, AndOrCriteriaGroup... subCriteria) { return new AndOrCriteriaGroup.Builder() .withConnector("or") //$NON-NLS-1$ .withInitialCriterion(initialCriterion) @@ -358,7 +358,7 @@ static AndOrCriteriaGroup or(List subCriteria) { } static AndOrCriteriaGroup and(BindableColumn column, VisitableCondition condition, - AndOrCriteriaGroup...subCriteria) { + AndOrCriteriaGroup... subCriteria) { return new AndOrCriteriaGroup.Builder() .withInitialCriterion(ColumnAndConditionCriterion.withColumn(column) .withCondition(condition) @@ -368,7 +368,7 @@ static AndOrCriteriaGroup and(BindableColumn column, VisitableCondition IsLessThanOrEqualTo isLessThanOrEqualToWhenPresent(Supplier val } @SafeVarargs - static IsIn isIn(T...values) { + static IsIn isIn(T... values) { return IsIn.of(values); } @@ -670,7 +670,7 @@ static IsInWithSubselect isIn(Buildable selectModelBuilder) } @SafeVarargs - static IsIn isInWhenPresent(T...values) { + static IsIn isInWhenPresent(T... values) { return IsIn.of(values).filter(Objects::nonNull); } @@ -679,7 +679,7 @@ static IsIn isInWhenPresent(Collection values) { } @SafeVarargs - static IsNotIn isNotIn(T...values) { + static IsNotIn isNotIn(T... values) { return IsNotIn.of(values); } @@ -692,7 +692,7 @@ static IsNotInWithSubselect isNotIn(Buildable selectModelBui } @SafeVarargs - static IsNotIn isNotInWhenPresent(T...values) { + static IsNotIn isNotInWhenPresent(T... values) { return IsNotIn.of(values).filter(Objects::nonNull); } @@ -807,7 +807,7 @@ static IsNotLikeCaseInsensitive isNotLikeCaseInsensitiveWhenPresent(Supplier values) { return IsInCaseInsensitive.of(values); } - static IsInCaseInsensitive isInCaseInsensitiveWhenPresent(String...values) { + static IsInCaseInsensitive isInCaseInsensitiveWhenPresent(String... values) { return IsInCaseInsensitive.of(values).filter(Objects::nonNull); } @@ -823,7 +823,7 @@ static IsInCaseInsensitive isInCaseInsensitiveWhenPresent(Collection val return values == null ? IsInCaseInsensitive.empty() : IsInCaseInsensitive.of(values).filter(Objects::nonNull); } - static IsNotInCaseInsensitive isNotInCaseInsensitive(String...values) { + static IsNotInCaseInsensitive isNotInCaseInsensitive(String... values) { return IsNotInCaseInsensitive.of(values); } @@ -831,7 +831,7 @@ static IsNotInCaseInsensitive isNotInCaseInsensitive(Collection values) return IsNotInCaseInsensitive.of(values); } - static IsNotInCaseInsensitive isNotInCaseInsensitiveWhenPresent(String...values) { + static IsNotInCaseInsensitive isNotInCaseInsensitiveWhenPresent(String... values) { return IsNotInCaseInsensitive.of(values).filter(Objects::nonNull); } @@ -885,7 +885,7 @@ public InsertSelectDSL withSelectStatement(Buildable selectModelBui .withSelectStatement(selectModelBuilder); } - public InsertSelectDSL.SelectGatherer withColumnList(SqlColumn...columns) { + public InsertSelectDSL.SelectGatherer withColumnList(SqlColumn... columns) { return InsertSelectDSL.insertInto(table) .withColumnList(columns); } diff --git a/src/main/java/org/mybatis/dynamic/sql/configuration/GlobalConfiguration.java b/src/main/java/org/mybatis/dynamic/sql/configuration/GlobalConfiguration.java index ee3ec16d7..336f1aecc 100644 --- a/src/main/java/org/mybatis/dynamic/sql/configuration/GlobalConfiguration.java +++ b/src/main/java/org/mybatis/dynamic/sql/configuration/GlobalConfiguration.java @@ -24,7 +24,7 @@ public class GlobalConfiguration { private static boolean unrenderableWhereClauseAllowed = false; static { - String propertyFile = "mybatis-dynamic-sql.properties"; + String propertyFile = "mybatis-dynamic-sql.properties"; try (InputStream is = GlobalConfiguration.class.getResourceAsStream(propertyFile)) { if (is != null) { Properties p = new Properties(); diff --git a/src/main/java/org/mybatis/dynamic/sql/exception/UnrenderableWhereClauseException.java b/src/main/java/org/mybatis/dynamic/sql/exception/UnrenderableWhereClauseException.java index f68e3afb2..2cd524b86 100644 --- a/src/main/java/org/mybatis/dynamic/sql/exception/UnrenderableWhereClauseException.java +++ b/src/main/java/org/mybatis/dynamic/sql/exception/UnrenderableWhereClauseException.java @@ -22,13 +22,13 @@ * This exception is thrown when the where clause in a statement will not render. * This can happen if all the optional conditions in a where clause fail to * render - for example, if an "in" condition specifies an empty list. - *

- * By default, the framework will throw this exception if a where clause + * + *

By default, the framework will throw this exception if a where clause * fails to render. A where clause that fails to render can be very dangerous in that * it could cause all rows in a table to be affected by a statement - for example, * all rows could be deleted. - *

- * If you intend to allow an unrenderable where clause, then configure the + * + *

If you intend to allow an unrenderable where clause, then configure the * statement to allow it, or change the global configuration. * * @see GlobalConfiguration 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 2baa0ca30..076989e0e 100644 --- a/src/main/java/org/mybatis/dynamic/sql/insert/BatchInsertDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/insert/BatchInsertDSL.java @@ -57,7 +57,7 @@ public BatchInsertModel build() { } @SafeVarargs - public static IntoGatherer insert(T...records) { + public static IntoGatherer insert(T... records) { return BatchInsertDSL.insert(Arrays.asList(records)); } diff --git a/src/main/java/org/mybatis/dynamic/sql/insert/InsertSelectDSL.java b/src/main/java/org/mybatis/dynamic/sql/insert/InsertSelectDSL.java index 55821162a..0262ed550 100644 --- a/src/main/java/org/mybatis/dynamic/sql/insert/InsertSelectDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/insert/InsertSelectDSL.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2022 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. @@ -63,7 +63,7 @@ private InsertColumnGatherer(SqlTable table) { this.table = table; } - public SelectGatherer withColumnList(SqlColumn...columns) { + public SelectGatherer withColumnList(SqlColumn... columns) { return withColumnList(Arrays.asList(columns)); } 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 0ccb426ac..1dac3dcb7 100644 --- a/src/main/java/org/mybatis/dynamic/sql/insert/MultiRowInsertDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/insert/MultiRowInsertDSL.java @@ -56,7 +56,7 @@ public MultiRowInsertModel build() { } @SafeVarargs - public static IntoGatherer insert(T...records) { + public static IntoGatherer insert(T... records) { return MultiRowInsertDSL.insert(Arrays.asList(records)); } 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 5a4d311a4..1cabb6300 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/AbstractQueryExpressionDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/AbstractQueryExpressionDSL.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2021 the original author or authors. + * Copyright 2016-2022 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. @@ -53,13 +53,13 @@ public TableExpression table() { } public T join(SqlTable joinTable, JoinCriterion onJoinCriterion, - JoinCriterion...andJoinCriteria) { + JoinCriterion... andJoinCriteria) { addJoinSpecificationBuilder(joinTable, onJoinCriterion, JoinType.INNER, Arrays.asList(andJoinCriteria)); return getThis(); } public T join(SqlTable joinTable, String tableAlias, JoinCriterion onJoinCriterion, - JoinCriterion...andJoinCriteria) { + JoinCriterion... andJoinCriteria) { addTableAlias(joinTable, tableAlias); return join(joinTable, onJoinCriterion, andJoinCriteria); } @@ -84,13 +84,13 @@ public T join(Buildable subQuery, String tableAlias, JoinCriterion } public T leftJoin(SqlTable joinTable, JoinCriterion onJoinCriterion, - JoinCriterion...andJoinCriteria) { + JoinCriterion... andJoinCriteria) { addJoinSpecificationBuilder(joinTable, onJoinCriterion, JoinType.LEFT, Arrays.asList(andJoinCriteria)); return getThis(); } public T leftJoin(SqlTable joinTable, String tableAlias, JoinCriterion onJoinCriterion, - JoinCriterion...andJoinCriteria) { + JoinCriterion... andJoinCriteria) { addTableAlias(joinTable, tableAlias); return leftJoin(joinTable, onJoinCriterion, andJoinCriteria); } @@ -115,13 +115,13 @@ public T leftJoin(Buildable subQuery, String tableAlias, JoinCriter } public T rightJoin(SqlTable joinTable, JoinCriterion onJoinCriterion, - JoinCriterion...andJoinCriteria) { + JoinCriterion... andJoinCriteria) { addJoinSpecificationBuilder(joinTable, onJoinCriterion, JoinType.RIGHT, Arrays.asList(andJoinCriteria)); return getThis(); } public T rightJoin(SqlTable joinTable, String tableAlias, JoinCriterion onJoinCriterion, - JoinCriterion...andJoinCriteria) { + JoinCriterion... andJoinCriteria) { addTableAlias(joinTable, tableAlias); return rightJoin(joinTable, onJoinCriterion, andJoinCriteria); } @@ -146,13 +146,13 @@ public T rightJoin(Buildable subQuery, String tableAlias, JoinCrite } public T fullJoin(SqlTable joinTable, JoinCriterion onJoinCriterion, - JoinCriterion...andJoinCriteria) { + JoinCriterion... andJoinCriteria) { addJoinSpecificationBuilder(joinTable, onJoinCriterion, JoinType.FULL, Arrays.asList(andJoinCriteria)); return getThis(); } public T fullJoin(SqlTable joinTable, String tableAlias, JoinCriterion onJoinCriterion, - JoinCriterion...andJoinCriteria) { + JoinCriterion... andJoinCriteria) { addTableAlias(joinTable, tableAlias); return fullJoin(joinTable, onJoinCriterion, andJoinCriteria); } diff --git a/src/main/java/org/mybatis/dynamic/sql/select/QueryExpressionDSL.java b/src/main/java/org/mybatis/dynamic/sql/select/QueryExpressionDSL.java index d8e134a85..665c3445e 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/QueryExpressionDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/QueryExpressionDSL.java @@ -133,7 +133,7 @@ public JoinSpecificationStarter fullJoin(Buildable joinTable, Strin return new JoinSpecificationStarter(buildSubQuery(joinTable, tableAlias), JoinType.FULL); } - public GroupByFinisher groupBy(BasicColumn...columns) { + public GroupByFinisher groupBy(BasicColumn... columns) { return groupBy(Arrays.asList(columns)); } @@ -142,7 +142,7 @@ public GroupByFinisher groupBy(Collection columns) { return new GroupByFinisher(); } - public SelectDSL orderBy(SortSpecification...columns) { + public SelectDSL orderBy(SortSpecification... columns) { return orderBy(Arrays.asList(columns)); } @@ -263,7 +263,7 @@ public UnionBuilder unionAll() { return QueryExpressionDSL.this.unionAll(); } - public SelectDSL orderBy(SortSpecification...columns) { + public SelectDSL orderBy(SortSpecification... columns) { return orderBy(Arrays.asList(columns)); } @@ -271,7 +271,7 @@ public SelectDSL orderBy(Collection columns) { return QueryExpressionDSL.this.orderBy(columns); } - public GroupByFinisher groupBy(BasicColumn...columns) { + public GroupByFinisher groupBy(BasicColumn... columns) { return groupBy(Arrays.asList(columns)); } @@ -321,7 +321,7 @@ public JoinSpecificationFinisher on(BasicColumn joinColumn, JoinCondition joinCo } public JoinSpecificationFinisher on(BasicColumn joinColumn, JoinCondition onJoinCondition, - JoinCriterion...andJoinCriteria) { + JoinCriterion... andJoinCriteria) { return new JoinSpecificationFinisher(joinTable, joinColumn, onJoinCondition, joinType, andJoinCriteria); } } @@ -346,7 +346,7 @@ public JoinSpecificationFinisher(TableExpression table, BasicColumn joinColumn, } public JoinSpecificationFinisher(TableExpression table, BasicColumn joinColumn, - JoinCondition joinCondition, JoinType joinType, JoinCriterion...andJoinCriteria) { + JoinCondition joinCondition, JoinType joinType, JoinCriterion... andJoinCriteria) { JoinCriterion onJoinCriterion = new JoinCriterion.Builder() .withConnector("on") //$NON-NLS-1$ .withJoinColumn(joinColumn) @@ -430,7 +430,7 @@ public JoinSpecificationStarter fullJoin(Buildable joinTable, Strin return QueryExpressionDSL.this.fullJoin(joinTable, tableAlias); } - public GroupByFinisher groupBy(BasicColumn...columns) { + public GroupByFinisher groupBy(BasicColumn... columns) { return groupBy(Arrays.asList(columns)); } @@ -446,7 +446,7 @@ public UnionBuilder unionAll() { return QueryExpressionDSL.this.unionAll(); } - public SelectDSL orderBy(SortSpecification...columns) { + public SelectDSL orderBy(SortSpecification... columns) { return orderBy(Arrays.asList(columns)); } @@ -468,7 +468,7 @@ public SelectDSL.FetchFirstFinisher fetchFirst(long fetchFirstRows) { } public class GroupByFinisher implements Buildable { - public SelectDSL orderBy(SortSpecification...columns) { + public SelectDSL orderBy(SortSpecification... columns) { return orderBy(Arrays.asList(columns)); } @@ -510,7 +510,7 @@ public UnionBuilder(String connector) { this.connector = connector; } - public FromGatherer select(BasicColumn...selectList) { + public FromGatherer select(BasicColumn... selectList) { return select(Arrays.asList(selectList)); } @@ -522,7 +522,7 @@ public FromGatherer select(List selectList) { .build(); } - public FromGatherer selectDistinct(BasicColumn...selectList) { + public FromGatherer selectDistinct(BasicColumn... selectList) { return selectDistinct(Arrays.asList(selectList)); } 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 c5b850ab7..c11de060a 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/SelectDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/SelectDSL.java @@ -54,7 +54,7 @@ private SelectDSL(Function adapterFunction) { this.adapterFunction = Objects.requireNonNull(adapterFunction); } - public static QueryExpressionDSL.FromGatherer select(BasicColumn...selectList) { + public static QueryExpressionDSL.FromGatherer select(BasicColumn... selectList) { return select(Arrays.asList(selectList)); } @@ -63,7 +63,7 @@ public static QueryExpressionDSL.FromGatherer select(Collection QueryExpressionDSL.FromGatherer select(Function adapterFunction, - BasicColumn...selectList) { + BasicColumn... selectList) { return select(adapterFunction, Arrays.asList(selectList)); } @@ -75,7 +75,7 @@ public static QueryExpressionDSL.FromGatherer select(Function selectDistinct(BasicColumn...selectList) { + public static QueryExpressionDSL.FromGatherer selectDistinct(BasicColumn... selectList) { return selectDistinct(Function.identity(), selectList); } @@ -84,7 +84,7 @@ public static QueryExpressionDSL.FromGatherer selectDistinct(Collec } public static QueryExpressionDSL.FromGatherer selectDistinct(Function adapterFunction, - BasicColumn...selectList) { + BasicColumn... selectList) { return selectDistinct(adapterFunction, Arrays.asList(selectList)); } diff --git a/src/main/java/org/mybatis/dynamic/sql/select/SelectDSLCompleter.java b/src/main/java/org/mybatis/dynamic/sql/select/SelectDSLCompleter.java index beccf5659..a720e8cce 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/SelectDSLCompleter.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/SelectDSLCompleter.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2022 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. @@ -89,7 +89,7 @@ static SelectDSLCompleter allRows() { * @param columns list of sort specifications for an order by clause * @return the completer that will select every row in a table with specified order */ - static SelectDSLCompleter allRowsOrderedBy(SortSpecification...columns) { + static SelectDSLCompleter allRowsOrderedBy(SortSpecification... columns) { return c -> c.orderBy(columns); } } diff --git a/src/main/java/org/mybatis/dynamic/sql/util/ConfigurableStatement.java b/src/main/java/org/mybatis/dynamic/sql/util/ConfigurableStatement.java index c6a86a135..bc9b1527d 100644 --- a/src/main/java/org/mybatis/dynamic/sql/util/ConfigurableStatement.java +++ b/src/main/java/org/mybatis/dynamic/sql/util/ConfigurableStatement.java @@ -15,10 +15,10 @@ */ package org.mybatis.dynamic.sql.util; -import org.mybatis.dynamic.sql.configuration.StatementConfiguration; - import java.util.function.Consumer; +import org.mybatis.dynamic.sql.configuration.StatementConfiguration; + public interface ConfigurableStatement { R configureStatement(Consumer consumer); } diff --git a/src/main/java/org/mybatis/dynamic/sql/util/springbatch/SpringBatchUtility.java b/src/main/java/org/mybatis/dynamic/sql/util/springbatch/SpringBatchUtility.java index f1ab9b504..166e3d880 100644 --- a/src/main/java/org/mybatis/dynamic/sql/util/springbatch/SpringBatchUtility.java +++ b/src/main/java/org/mybatis/dynamic/sql/util/springbatch/SpringBatchUtility.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2022 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. @@ -48,7 +48,7 @@ public static Map toParameterValues(SelectStatementProvider sele * @return FromGatherer used to continue a SELECT statement */ public static QueryExpressionDSL.FromGatherer selectForPaging( - BasicColumn...selectList) { + BasicColumn... selectList) { return SelectDSL.select(SpringBatchPagingReaderSelectModel::new, selectList); } @@ -59,7 +59,7 @@ public static QueryExpressionDSL.FromGatherer selectForCursor( - BasicColumn...selectList) { + BasicColumn... selectList) { return SelectDSL.select(SpringBatchCursorReaderSelectModel::new, selectList); } } diff --git a/src/main/java/org/mybatis/dynamic/sql/where/AbstractWhereDSL.java b/src/main/java/org/mybatis/dynamic/sql/where/AbstractWhereDSL.java index 85d424ca1..aee7fda22 100644 --- a/src/main/java/org/mybatis/dynamic/sql/where/AbstractWhereDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/where/AbstractWhereDSL.java @@ -51,7 +51,7 @@ public T configureStatement(Consumer consumer) { @NotNull public T where(BindableColumn column, VisitableCondition condition, - AndOrCriteriaGroup...subCriteria) { + AndOrCriteriaGroup... subCriteria) { return where(column, condition, Arrays.asList(subCriteria)); } @@ -66,7 +66,7 @@ public T where(BindableColumn column, VisitableCondition condition, } @NotNull - public T where(ExistsPredicate existsPredicate, AndOrCriteriaGroup...subCriteria) { + public T where(ExistsPredicate existsPredicate, AndOrCriteriaGroup... subCriteria) { return where(existsPredicate, Arrays.asList(subCriteria)); } @@ -78,7 +78,7 @@ public T where(ExistsPredicate existsPredicate, List subCrit } @NotNull - public T where(SqlCriterion initialCriterion, AndOrCriteriaGroup...subCriteria) { + public T where(SqlCriterion initialCriterion, AndOrCriteriaGroup... subCriteria) { return where(initialCriterion, Arrays.asList(subCriteria)); } @@ -107,7 +107,7 @@ public T applyWhere(WhereApplier whereApplier) { @NotNull public T and(BindableColumn column, VisitableCondition condition, - AndOrCriteriaGroup...subCriteria) { + AndOrCriteriaGroup... subCriteria) { return and(column, condition, Arrays.asList(subCriteria)); } @@ -119,7 +119,7 @@ public T and(BindableColumn column, VisitableCondition condition, } @NotNull - public T and(ExistsPredicate existsPredicate, AndOrCriteriaGroup...subCriteria) { + public T and(ExistsPredicate existsPredicate, AndOrCriteriaGroup... subCriteria) { return and(existsPredicate, Arrays.asList(subCriteria)); } @@ -130,7 +130,7 @@ public T and(ExistsPredicate existsPredicate, List subCriter } @NotNull - public T and(SqlCriterion initialCriterion, AndOrCriteriaGroup...subCriteria) { + public T and(SqlCriterion initialCriterion, AndOrCriteriaGroup... subCriteria) { return and(initialCriterion, Arrays.asList(subCriteria)); } @@ -148,7 +148,7 @@ public T and(List criteria) { @NotNull public T or(BindableColumn column, VisitableCondition condition, - AndOrCriteriaGroup...subCriteria) { + AndOrCriteriaGroup... subCriteria) { return or(column, condition, Arrays.asList(subCriteria)); } @@ -160,7 +160,7 @@ public T or(BindableColumn column, VisitableCondition condition, } @NotNull - public T or(ExistsPredicate existsPredicate, AndOrCriteriaGroup...subCriteria) { + public T or(ExistsPredicate existsPredicate, AndOrCriteriaGroup... subCriteria) { return or(existsPredicate, Arrays.asList(subCriteria)); } @@ -171,7 +171,7 @@ public T or(ExistsPredicate existsPredicate, List subCriteri } @NotNull - public T or(SqlCriterion initialCriterion, AndOrCriteriaGroup...subCriteria) { + public T or(SqlCriterion initialCriterion, AndOrCriteriaGroup... subCriteria) { return or(initialCriterion, Arrays.asList(subCriteria)); } diff --git a/src/main/java/org/mybatis/dynamic/sql/where/AbstractWhereSupport.java b/src/main/java/org/mybatis/dynamic/sql/where/AbstractWhereSupport.java index 3a4d46523..29384e153 100644 --- a/src/main/java/org/mybatis/dynamic/sql/where/AbstractWhereSupport.java +++ b/src/main/java/org/mybatis/dynamic/sql/where/AbstractWhereSupport.java @@ -37,7 +37,7 @@ public abstract class AbstractWhereSupport> { public abstract W where(); - public W where(BindableColumn column, VisitableCondition condition, AndOrCriteriaGroup...subCriteria) { + public W where(BindableColumn column, VisitableCondition condition, AndOrCriteriaGroup... subCriteria) { return where(column, condition, Arrays.asList(subCriteria)); } @@ -46,7 +46,7 @@ public W where(BindableColumn column, VisitableCondition condition, return apply(w -> w.where(column, condition, subCriteria)); } - public W where(ExistsPredicate existsPredicate, AndOrCriteriaGroup...subCriteria) { + public W where(ExistsPredicate existsPredicate, AndOrCriteriaGroup... subCriteria) { return where(existsPredicate, Arrays.asList(subCriteria)); } @@ -54,7 +54,7 @@ public W where(ExistsPredicate existsPredicate, List subCrit return apply(w -> w.where(existsPredicate, subCriteria)); } - public W where(SqlCriterion initialCriterion, AndOrCriteriaGroup...subCriteria) { + public W where(SqlCriterion initialCriterion, AndOrCriteriaGroup... subCriteria) { return where(initialCriterion, Arrays.asList(subCriteria)); } From 90cd2cc9c54cceb4ab11c73974bd84d4efdfe1c6 Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Tue, 16 Aug 2022 18:28:38 -0400 Subject: [PATCH 06/23] Use late initialization for where builders This solves a corner case for configuration when a where() method is called, but no criteria are added --- .../mybatis/dynamic/sql/delete/DeleteDSL.java | 18 +- .../mybatis/dynamic/sql/select/CountDSL.java | 15 +- .../sql/select/QueryExpressionDSL.java | 20 ++- .../mybatis/dynamic/sql/update/UpdateDSL.java | 22 ++- .../mybatis/dynamic/sql/where/WhereModel.java | 5 - .../sql/StatementConfigurationTest.java | 170 ++++++++++++++++++ 6 files changed, 218 insertions(+), 32 deletions(-) create mode 100644 src/test/java/org/mybatis/dynamic/sql/StatementConfigurationTest.java diff --git a/src/main/java/org/mybatis/dynamic/sql/delete/DeleteDSL.java b/src/main/java/org/mybatis/dynamic/sql/delete/DeleteDSL.java index 2a27b452d..7eb462a0d 100644 --- a/src/main/java/org/mybatis/dynamic/sql/delete/DeleteDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/delete/DeleteDSL.java @@ -31,18 +31,20 @@ public class DeleteDSL extends AbstractWhereSupport.DeleteWhereB private final Function adapterFunction; private final SqlTable table; private final String tableAlias; - private final DeleteWhereBuilder whereBuilder; + private DeleteWhereBuilder whereBuilder; private final StatementConfiguration statementConfiguration = new StatementConfiguration(); private DeleteDSL(SqlTable table, String tableAlias, Function adapterFunction) { this.table = Objects.requireNonNull(table); this.tableAlias = tableAlias; this.adapterFunction = Objects.requireNonNull(adapterFunction); - whereBuilder = new DeleteWhereBuilder(); } @Override public DeleteWhereBuilder where() { + if (whereBuilder == null) { + whereBuilder = new DeleteWhereBuilder(); + } return whereBuilder; } @@ -55,11 +57,13 @@ public DeleteWhereBuilder where() { @NotNull @Override public R build() { - DeleteModel deleteModel = DeleteModel.withTable(table) - .withTableAlias(tableAlias) - .withWhereModel(whereBuilder.buildWhereModel()) - .build(); - return adapterFunction.apply(deleteModel); + DeleteModel.Builder deleteModelBuilder = DeleteModel.withTable(table) + .withTableAlias(tableAlias); + if (whereBuilder != null) { + deleteModelBuilder.withWhereModel(whereBuilder.buildWhereModel()); + } + + return adapterFunction.apply(deleteModelBuilder.build()); } public static DeleteDSL deleteFrom(Function adapterFunction, SqlTable table, diff --git a/src/main/java/org/mybatis/dynamic/sql/select/CountDSL.java b/src/main/java/org/mybatis/dynamic/sql/select/CountDSL.java index b11fe5d01..6f88a97a7 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/CountDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/CountDSL.java @@ -40,7 +40,7 @@ public class CountDSL extends AbstractQueryExpressionDSL.CountWhe implements Buildable { private final Function adapterFunction; - private final CountWhereBuilder whereBuilder; + private CountWhereBuilder whereBuilder; private final BasicColumn countColumn; private final StatementConfiguration statementConfiguration = new StatementConfiguration(); @@ -48,11 +48,13 @@ private CountDSL(BasicColumn countColumn, SqlTable table, Function from(SqlTable table) { public class CountWhereBuilder extends AbstractWhereDSL implements Buildable { - private CountWhereBuilder(StatementConfiguration statementConfiguration) { + private CountWhereBuilder() { super(statementConfiguration); } diff --git a/src/main/java/org/mybatis/dynamic/sql/select/QueryExpressionDSL.java b/src/main/java/org/mybatis/dynamic/sql/select/QueryExpressionDSL.java index 665c3445e..44e349c38 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/QueryExpressionDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/QueryExpressionDSL.java @@ -46,7 +46,7 @@ public class QueryExpressionDSL private final SelectDSL selectDSL; private final boolean isDistinct; private final List selectList; - private final QueryExpressionWhereBuilder whereBuilder; + private QueryExpressionWhereBuilder whereBuilder; private GroupByModel groupByModel; private final StatementConfiguration statementConfiguration = new StatementConfiguration(); @@ -56,7 +56,6 @@ public class QueryExpressionDSL selectList = fromGatherer.selectList; isDistinct = fromGatherer.isDistinct; selectDSL = Objects.requireNonNull(fromGatherer.selectDSL); - whereBuilder = new QueryExpressionWhereBuilder(statementConfiguration); } QueryExpressionDSL(FromGatherer fromGatherer, SqlTable table, String tableAlias) { @@ -66,6 +65,9 @@ public class QueryExpressionDSL @Override public QueryExpressionWhereBuilder where() { + if (whereBuilder == null) { + whereBuilder = new QueryExpressionWhereBuilder(); + } return whereBuilder; } @@ -160,15 +162,19 @@ public UnionBuilder unionAll() { } protected QueryExpressionModel buildModel() { - return QueryExpressionModel.withSelectList(selectList) + QueryExpressionModel.Builder builder = QueryExpressionModel.withSelectList(selectList) .withConnector(connector) .withTable(table()) .isDistinct(isDistinct) .withTableAliases(tableAliases()) - .withWhereModel(whereBuilder.buildWhereModel()) .withJoinModel(buildJoinModel().orElse(null)) - .withGroupByModel(groupByModel) - .build(); + .withGroupByModel(groupByModel); + + if (whereBuilder != null) { + builder.withWhereModel(whereBuilder.buildWhereModel()); + } + + return builder.build(); } public SelectDSL.LimitFinisher limit(long limit) { @@ -251,7 +257,7 @@ public FromGatherer build() { public class QueryExpressionWhereBuilder extends AbstractWhereDSL implements Buildable { - private QueryExpressionWhereBuilder(StatementConfiguration statementConfiguration) { + private QueryExpressionWhereBuilder() { super(statementConfiguration); } diff --git a/src/main/java/org/mybatis/dynamic/sql/update/UpdateDSL.java b/src/main/java/org/mybatis/dynamic/sql/update/UpdateDSL.java index 378afdd29..b3512450c 100644 --- a/src/main/java/org/mybatis/dynamic/sql/update/UpdateDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/update/UpdateDSL.java @@ -47,14 +47,13 @@ public class UpdateDSL extends AbstractWhereSupport.UpdateWhereB private final List columnMappings = new ArrayList<>(); private final SqlTable table; private final String tableAlias; - private final UpdateWhereBuilder whereBuilder; + private UpdateWhereBuilder whereBuilder; private final StatementConfiguration statementConfiguration = new StatementConfiguration(); private UpdateDSL(SqlTable table, String tableAlias, Function adapterFunction) { this.table = Objects.requireNonNull(table); this.tableAlias = tableAlias; this.adapterFunction = Objects.requireNonNull(adapterFunction); - whereBuilder = new UpdateWhereBuilder(statementConfiguration); } public SetClauseFinisher set(SqlColumn column) { @@ -63,6 +62,10 @@ public SetClauseFinisher set(SqlColumn column) { @Override public UpdateWhereBuilder where() { + if (whereBuilder == null) { + whereBuilder = new UpdateWhereBuilder(); + } + return whereBuilder; } @@ -75,12 +78,15 @@ public UpdateWhereBuilder where() { @NotNull @Override public R build() { - UpdateModel updateModel = UpdateModel.withTable(table) + UpdateModel.Builder updateModelBuilder = UpdateModel.withTable(table) .withTableAlias(tableAlias) - .withColumnMappings(columnMappings) - .withWhereModel(whereBuilder.buildWhereModel()) - .build(); - return adapterFunction.apply(updateModel); + .withColumnMappings(columnMappings); + + if (whereBuilder != null) { + updateModelBuilder.withWhereModel(whereBuilder.buildWhereModel()); + } + + return adapterFunction.apply(updateModelBuilder.build()); } public static UpdateDSL update(Function adapterFunction, SqlTable table, String tableAlias) { @@ -158,7 +164,7 @@ public UpdateDSL equalToWhenPresent(Supplier valueSupplier) { public class UpdateWhereBuilder extends AbstractWhereDSL implements Buildable { - private UpdateWhereBuilder(StatementConfiguration statementConfiguration) { + private UpdateWhereBuilder() { super(statementConfiguration); } diff --git a/src/main/java/org/mybatis/dynamic/sql/where/WhereModel.java b/src/main/java/org/mybatis/dynamic/sql/where/WhereModel.java index 0d2b5db97..2a05b1638 100644 --- a/src/main/java/org/mybatis/dynamic/sql/where/WhereModel.java +++ b/src/main/java/org/mybatis/dynamic/sql/where/WhereModel.java @@ -55,11 +55,6 @@ public List subCriteria() { } public boolean isUnrenderableClauseAllowed() { - // if no criteria were specified, then no where clause was expected - if (initialCriterion == null && subCriteria.isEmpty()) { - return true; - } - return statementConfiguration.getUnrenderableWhereClauseAllowed(); } diff --git a/src/test/java/org/mybatis/dynamic/sql/StatementConfigurationTest.java b/src/test/java/org/mybatis/dynamic/sql/StatementConfigurationTest.java new file mode 100644 index 000000000..679c4fcb1 --- /dev/null +++ b/src/test/java/org/mybatis/dynamic/sql/StatementConfigurationTest.java @@ -0,0 +1,170 @@ +/* + * Copyright 2016-2022 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; + +import static examples.complexquery.PersonDynamicSqlSupport.firstName; +import static examples.complexquery.PersonDynamicSqlSupport.id; +import static examples.complexquery.PersonDynamicSqlSupport.lastName; +import static examples.complexquery.PersonDynamicSqlSupport.person; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.mybatis.dynamic.sql.SqlBuilder.countFrom; +import static org.mybatis.dynamic.sql.SqlBuilder.deleteFrom; +import static org.mybatis.dynamic.sql.SqlBuilder.select; +import static org.mybatis.dynamic.sql.SqlBuilder.update; + +import org.junit.jupiter.api.Test; +import org.mybatis.dynamic.sql.delete.render.DeleteStatementProvider; +import org.mybatis.dynamic.sql.exception.UnrenderableWhereClauseException; +import org.mybatis.dynamic.sql.render.RenderingStrategies; +import org.mybatis.dynamic.sql.select.render.SelectStatementProvider; +import org.mybatis.dynamic.sql.update.render.UpdateStatementProvider; + +public class StatementConfigurationTest { + @Test + void testCountWhereCalledButNoCriteriaThrowsException() { + assertThatExceptionOfType(UnrenderableWhereClauseException.class).isThrownBy(() -> + countFrom(person) + .where() + .build() + .render(RenderingStrategies.MYBATIS3) + ); + } + + @Test + void testCountWhereCalledButNoCriteriaRequiresConfiguration() { + SelectStatementProvider selectStatement = countFrom(person) + .where() + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .build() + .render(RenderingStrategies.MYBATIS3); + + assertThat(selectStatement.getSelectStatement()) + .isEqualTo("select count(*) from Person"); + } + + @Test + void testCountWhereNotCalledIsOK() { + SelectStatementProvider selectStatement = countFrom(person) + .build() + .render(RenderingStrategies.MYBATIS3); + + assertThat(selectStatement.getSelectStatement()) + .isEqualTo("select count(*) from Person"); + } + + @Test + void testDeleteWhereCalledButNoCriteriaThrowsException() { + assertThatExceptionOfType(UnrenderableWhereClauseException.class).isThrownBy(() -> + deleteFrom(person) + .where() + .build() + .render(RenderingStrategies.MYBATIS3) + ); + } + + @Test + void testDeleteWhereCalledButNoCriteriaRequiresConfiguration() { + DeleteStatementProvider deleteStatement = deleteFrom(person) + .where() + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .build() + .render(RenderingStrategies.MYBATIS3); + + assertThat(deleteStatement.getDeleteStatement()) + .isEqualTo("delete from Person"); + } + + @Test + void testDeleteWhereNotCalledIsOK() { + DeleteStatementProvider deleteStatement = deleteFrom(person) + .build() + .render(RenderingStrategies.MYBATIS3); + + assertThat(deleteStatement.getDeleteStatement()) + .isEqualTo("delete from Person"); + } + + @Test + void testSelectWhereCalledButNoCriteriaThrowsException() { + assertThatExceptionOfType(UnrenderableWhereClauseException.class).isThrownBy(() -> + select(id, firstName, lastName) + .from(person) + .where() + .build() + .render(RenderingStrategies.MYBATIS3) + ); + } + + @Test + void testSelectWhereCalledButNoCriteriaRequiresConfiguration() { + SelectStatementProvider selectStatement = select(id, firstName, lastName) + .from(person) + .where() + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .build() + .render(RenderingStrategies.MYBATIS3); + + assertThat(selectStatement.getSelectStatement()) + .isEqualTo("select person_id, first_name, last_name from Person"); + } + + @Test + void testSelectWhereNotCalledIsOK() { + SelectStatementProvider selectStatement = select(id, firstName, lastName) + .from(person) + .build() + .render(RenderingStrategies.MYBATIS3); + + assertThat(selectStatement.getSelectStatement()) + .isEqualTo("select person_id, first_name, last_name from Person"); + } + + @Test + void testUpdateWhereCalledButNoCriteriaThrowsException() { + assertThatExceptionOfType(UnrenderableWhereClauseException.class).isThrownBy(() -> + update(person) + .set(id).equalTo(1) + .where() + .build() + .render(RenderingStrategies.MYBATIS3) + ); + } + + @Test + void testUpdateWhereCalledButNoCriteriaRequiresConfiguration() { + UpdateStatementProvider updateStatement = update(person) + .set(id).equalTo(1) + .where() + .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .build() + .render(RenderingStrategies.MYBATIS3); + + assertThat(updateStatement.getUpdateStatement()) + .isEqualTo("update Person set person_id = #{parameters.p1}"); + } + + @Test + void testUpdateWhereNotCalledIsOK() { + UpdateStatementProvider updateStatement = update(person) + .set(id).equalTo(1) + .build() + .render(RenderingStrategies.MYBATIS3); + + assertThat(updateStatement.getUpdateStatement()) + .isEqualTo("update Person set person_id = #{parameters.p1}"); + } +} From 03e11b8616475177511006b50a0b68812d08fba7 Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Tue, 16 Aug 2022 18:44:41 -0400 Subject: [PATCH 07/23] Polishing --- .../org/mybatis/dynamic/sql/select/CountDSL.java | 2 +- .../dynamic/sql/where/render/WhereRenderer.java | 4 ++-- .../kotlin/spring/canonical/InfixElementsTest.kt | 12 ------------ 3 files changed, 3 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/mybatis/dynamic/sql/select/CountDSL.java b/src/main/java/org/mybatis/dynamic/sql/select/CountDSL.java index 6f88a97a7..dc495fb2a 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/CountDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/CountDSL.java @@ -70,7 +70,7 @@ private SelectModel buildModel() { .withTable(table()) .withTableAliases(tableAliases()); - if (whereBuilder != null){ + if (whereBuilder != null) { b.withWhereModel(whereBuilder.buildWhereModel()); } diff --git a/src/main/java/org/mybatis/dynamic/sql/where/render/WhereRenderer.java b/src/main/java/org/mybatis/dynamic/sql/where/render/WhereRenderer.java index 552f60d96..9cb801e28 100644 --- a/src/main/java/org/mybatis/dynamic/sql/where/render/WhereRenderer.java +++ b/src/main/java/org/mybatis/dynamic/sql/where/render/WhereRenderer.java @@ -52,9 +52,9 @@ public Optional render() { if (whereClause.isPresent() || whereModel.isUnrenderableClauseAllowed()) { return whereClause; + } else { + throw new UnrenderableWhereClauseException(); } - - throw new UnrenderableWhereClauseException(); } private Optional renderWithInitialCriterion(SqlCriterion initialCriterion) { diff --git a/src/test/kotlin/examples/kotlin/spring/canonical/InfixElementsTest.kt b/src/test/kotlin/examples/kotlin/spring/canonical/InfixElementsTest.kt index 2bba78fee..4f44eb273 100644 --- a/src/test/kotlin/examples/kotlin/spring/canonical/InfixElementsTest.kt +++ b/src/test/kotlin/examples/kotlin/spring/canonical/InfixElementsTest.kt @@ -24,7 +24,6 @@ import examples.kotlin.spring.canonical.PersonDynamicSqlSupport.lastName import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThatExceptionOfType import org.junit.jupiter.api.Test -import org.mybatis.dynamic.sql.exception.UnrenderableWhereClauseException import org.mybatis.dynamic.sql.util.kotlin.KInvalidSQLException import org.mybatis.dynamic.sql.util.kotlin.elements.isLike import org.mybatis.dynamic.sql.util.kotlin.elements.stringConstant @@ -96,17 +95,6 @@ open class InfixElementsTest { assertThat(rows[0]).isEqualTo("Bamm Bamm") } - @Test - fun testVanishingWhereClause() { - assertThatExceptionOfType(UnrenderableWhereClauseException::class.java).isThrownBy { - select(firstName) { - from(person) - where { id isEqualToWhenPresent null } - orderBy(id) - } - } - } - @Test fun testIsEqualToWhenPresentNull() { val selectStatement = select(firstName) { From a03ab7f30753fe40eb9666105c0a9b8741d98f64 Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Wed, 24 Aug 2022 11:06:38 -0400 Subject: [PATCH 08/23] Rewrite for code coverage --- .../dynamic/sql/util/kotlin/KotlinSubQueryBuilders.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/KotlinSubQueryBuilders.kt b/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/KotlinSubQueryBuilders.kt index 3767e7aa8..c816da276 100644 --- a/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/KotlinSubQueryBuilders.kt +++ b/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/KotlinSubQueryBuilders.kt @@ -20,6 +20,7 @@ import org.mybatis.dynamic.sql.SqlBuilder import org.mybatis.dynamic.sql.SqlColumn import org.mybatis.dynamic.sql.select.SelectModel import org.mybatis.dynamic.sql.util.Buildable +import java.lang.NullPointerException @MyBatisDslMarker sealed class KotlinBaseSubQueryBuilder : Buildable { @@ -40,7 +41,11 @@ sealed class KotlinBaseSubQueryBuilder : Buildable { } override fun build(): SelectModel = - selectBuilder?.build()?: throw KInvalidSQLException("You must specify a select statement in a sub query") + try { + selectBuilder!!.build() + } catch (e: NullPointerException) { + throw KInvalidSQLException("You must specify a select statement in a sub query") + } } class KotlinSubQueryBuilder : KotlinBaseSubQueryBuilder() From 8e3e194d00686efc911499cdc6e2e175ea27417a Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Wed, 24 Aug 2022 11:07:06 -0400 Subject: [PATCH 09/23] Improve tests per Sonar recs --- .../sql/StatementConfigurationTest.java | 57 ++++++++++--------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/src/test/java/org/mybatis/dynamic/sql/StatementConfigurationTest.java b/src/test/java/org/mybatis/dynamic/sql/StatementConfigurationTest.java index 679c4fcb1..beca4c7b4 100644 --- a/src/test/java/org/mybatis/dynamic/sql/StatementConfigurationTest.java +++ b/src/test/java/org/mybatis/dynamic/sql/StatementConfigurationTest.java @@ -27,20 +27,24 @@ import static org.mybatis.dynamic.sql.SqlBuilder.update; import org.junit.jupiter.api.Test; +import org.mybatis.dynamic.sql.delete.DeleteModel; import org.mybatis.dynamic.sql.delete.render.DeleteStatementProvider; import org.mybatis.dynamic.sql.exception.UnrenderableWhereClauseException; import org.mybatis.dynamic.sql.render.RenderingStrategies; +import org.mybatis.dynamic.sql.select.SelectModel; import org.mybatis.dynamic.sql.select.render.SelectStatementProvider; +import org.mybatis.dynamic.sql.update.UpdateModel; import org.mybatis.dynamic.sql.update.render.UpdateStatementProvider; -public class StatementConfigurationTest { +class StatementConfigurationTest { @Test void testCountWhereCalledButNoCriteriaThrowsException() { + SelectModel selectModel = countFrom(person) + .where() + .build(); + assertThatExceptionOfType(UnrenderableWhereClauseException.class).isThrownBy(() -> - countFrom(person) - .where() - .build() - .render(RenderingStrategies.MYBATIS3) + selectModel.render(RenderingStrategies.MYBATIS3) ); } @@ -52,8 +56,7 @@ void testCountWhereCalledButNoCriteriaRequiresConfiguration() { .build() .render(RenderingStrategies.MYBATIS3); - assertThat(selectStatement.getSelectStatement()) - .isEqualTo("select count(*) from Person"); + assertThat(selectStatement.getSelectStatement()).isEqualTo("select count(*) from Person"); } @Test @@ -62,17 +65,17 @@ void testCountWhereNotCalledIsOK() { .build() .render(RenderingStrategies.MYBATIS3); - assertThat(selectStatement.getSelectStatement()) - .isEqualTo("select count(*) from Person"); + assertThat(selectStatement.getSelectStatement()).isEqualTo("select count(*) from Person"); } @Test void testDeleteWhereCalledButNoCriteriaThrowsException() { + DeleteModel deleteModel = deleteFrom(person) + .where() + .build(); + assertThatExceptionOfType(UnrenderableWhereClauseException.class).isThrownBy(() -> - deleteFrom(person) - .where() - .build() - .render(RenderingStrategies.MYBATIS3) + deleteModel.render(RenderingStrategies.MYBATIS3) ); } @@ -84,8 +87,7 @@ void testDeleteWhereCalledButNoCriteriaRequiresConfiguration() { .build() .render(RenderingStrategies.MYBATIS3); - assertThat(deleteStatement.getDeleteStatement()) - .isEqualTo("delete from Person"); + assertThat(deleteStatement.getDeleteStatement()).isEqualTo("delete from Person"); } @Test @@ -94,18 +96,18 @@ void testDeleteWhereNotCalledIsOK() { .build() .render(RenderingStrategies.MYBATIS3); - assertThat(deleteStatement.getDeleteStatement()) - .isEqualTo("delete from Person"); + assertThat(deleteStatement.getDeleteStatement()).isEqualTo("delete from Person"); } @Test void testSelectWhereCalledButNoCriteriaThrowsException() { + SelectModel selectModel = select(id, firstName, lastName) + .from(person) + .where() + .build(); + assertThatExceptionOfType(UnrenderableWhereClauseException.class).isThrownBy(() -> - select(id, firstName, lastName) - .from(person) - .where() - .build() - .render(RenderingStrategies.MYBATIS3) + selectModel.render(RenderingStrategies.MYBATIS3) ); } @@ -135,12 +137,13 @@ void testSelectWhereNotCalledIsOK() { @Test void testUpdateWhereCalledButNoCriteriaThrowsException() { + UpdateModel updateModel = update(person) + .set(id).equalTo(1) + .where() + .build(); + assertThatExceptionOfType(UnrenderableWhereClauseException.class).isThrownBy(() -> - update(person) - .set(id).equalTo(1) - .where() - .build() - .render(RenderingStrategies.MYBATIS3) + updateModel.render(RenderingStrategies.MYBATIS3) ); } From bc814e77925d77f195e1cf5230404917f80916d9 Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Wed, 24 Aug 2022 11:07:25 -0400 Subject: [PATCH 10/23] Improve code per Sonar recs --- .../mybatis/dynamic/sql/configuration/GlobalConfiguration.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/org/mybatis/dynamic/sql/configuration/GlobalConfiguration.java b/src/main/java/org/mybatis/dynamic/sql/configuration/GlobalConfiguration.java index 336f1aecc..2d579288c 100644 --- a/src/main/java/org/mybatis/dynamic/sql/configuration/GlobalConfiguration.java +++ b/src/main/java/org/mybatis/dynamic/sql/configuration/GlobalConfiguration.java @@ -23,6 +23,8 @@ public class GlobalConfiguration { private static boolean unrenderableWhereClauseAllowed = false; + private GlobalConfiguration() {} + static { String propertyFile = "mybatis-dynamic-sql.properties"; try (InputStream is = GlobalConfiguration.class.getResourceAsStream(propertyFile)) { From 2b68c9303ccbb286eb0f269adbb5e496b92cd14e Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Wed, 24 Aug 2022 11:41:18 -0400 Subject: [PATCH 11/23] Better Property Name --- .../configuration/GlobalConfiguration.java | 10 ++-- .../configuration/StatementConfiguration.java | 17 +++---- ... => NonRenderingWhereClauseException.java} | 6 +-- .../mybatis/dynamic/sql/where/WhereModel.java | 2 +- .../sql/where/render/WhereRenderer.java | 4 +- .../examples/animal/data/AnimalDataTest.java | 4 +- .../OptionalConditionsAnimalDataTest.java | 2 +- ...onditionsWithPredicatesAnimalDataTest.java | 2 +- .../complexquery/ComplexQueryTest.java | 2 +- .../examples/emptywhere/EmptyWhereTest.java | 10 ++-- src/test/java/issues/gh105/Issue105Test.java | 50 +++++++++---------- .../sql/StatementConfigurationTest.java | 18 +++---- .../sql/select/SelectStatementTest.java | 8 +-- .../render/OptionalCriterionRenderTest.java | 10 ++-- .../spring/canonical/InfixElementsTest.kt | 40 +++++++-------- .../spring/canonical/KotlinElementsTest.kt | 16 +++--- 16 files changed, 100 insertions(+), 101 deletions(-) rename src/main/java/org/mybatis/dynamic/sql/exception/{UnrenderableWhereClauseException.java => NonRenderingWhereClauseException.java} (89%) diff --git a/src/main/java/org/mybatis/dynamic/sql/configuration/GlobalConfiguration.java b/src/main/java/org/mybatis/dynamic/sql/configuration/GlobalConfiguration.java index 2d579288c..edff111cd 100644 --- a/src/main/java/org/mybatis/dynamic/sql/configuration/GlobalConfiguration.java +++ b/src/main/java/org/mybatis/dynamic/sql/configuration/GlobalConfiguration.java @@ -21,7 +21,7 @@ // TODO - read initial value from a properties file! public class GlobalConfiguration { - private static boolean unrenderableWhereClauseAllowed = false; + private static boolean isNonRenderingWhereClauseAllowed = false; private GlobalConfiguration() {} @@ -31,9 +31,9 @@ private GlobalConfiguration() {} if (is != null) { Properties p = new Properties(); p.load(is); - String value = p.getProperty("unrenderableWhereClauseAllowed"); + String value = p.getProperty("nonRenderingWhereClauseAllowed"); if (value != null) { - unrenderableWhereClauseAllowed = Boolean.parseBoolean(value); + isNonRenderingWhereClauseAllowed = Boolean.parseBoolean(value); } } } catch (IOException e) { @@ -41,7 +41,7 @@ private GlobalConfiguration() {} } } - public static boolean getUnrenderableWhereClauseAllowed() { - return unrenderableWhereClauseAllowed; + public static boolean isIsNonRenderingWhereClauseAllowed() { + return isNonRenderingWhereClauseAllowed; } } diff --git a/src/main/java/org/mybatis/dynamic/sql/configuration/StatementConfiguration.java b/src/main/java/org/mybatis/dynamic/sql/configuration/StatementConfiguration.java index be98f417b..a121197e2 100644 --- a/src/main/java/org/mybatis/dynamic/sql/configuration/StatementConfiguration.java +++ b/src/main/java/org/mybatis/dynamic/sql/configuration/StatementConfiguration.java @@ -15,7 +15,7 @@ */ package org.mybatis.dynamic.sql.configuration; -import org.mybatis.dynamic.sql.exception.UnrenderableWhereClauseException; +import org.mybatis.dynamic.sql.exception.NonRenderingWhereClauseException; /** * This class can be used to change some behaviors of the framework. Every configurable statement @@ -25,9 +25,8 @@ * Configurable behaviors are detailed below: * *

- *
unrenderableWhereClauseAllowed
- *
If false (default), the framework will throw an - * {@link UnrenderableWhereClauseException} + *
nonRenderingWhereClauseAllowed
+ *
If false (default), the framework will throw a {@link NonRenderingWhereClauseException} * if a where clause is specified in the statement, but it fails to render because all * optional conditions do not render. For example, if an "in" condition specifies an * empty list of values. If no criteria are specified in a where clause, the framework @@ -40,13 +39,13 @@ * @author Jeff Butler */ public class StatementConfiguration { - private boolean unrenderableWhereClauseAllowed = GlobalConfiguration.getUnrenderableWhereClauseAllowed(); + private boolean isNonRenderingWhereClauseAllowed = GlobalConfiguration.isIsNonRenderingWhereClauseAllowed(); - public boolean getUnrenderableWhereClauseAllowed() { - return unrenderableWhereClauseAllowed; + public boolean isNonRenderingWhereClauseAllowed() { + return isNonRenderingWhereClauseAllowed; } - public void setUnrenderableWhereClauseAllowed(boolean unrenderableWhereClauseAllowed) { - this.unrenderableWhereClauseAllowed = unrenderableWhereClauseAllowed; + public void setNonRenderingWhereClauseAllowed(boolean nonRenderingWhereClauseAllowed) { + this.isNonRenderingWhereClauseAllowed = nonRenderingWhereClauseAllowed; } } diff --git a/src/main/java/org/mybatis/dynamic/sql/exception/UnrenderableWhereClauseException.java b/src/main/java/org/mybatis/dynamic/sql/exception/NonRenderingWhereClauseException.java similarity index 89% rename from src/main/java/org/mybatis/dynamic/sql/exception/UnrenderableWhereClauseException.java rename to src/main/java/org/mybatis/dynamic/sql/exception/NonRenderingWhereClauseException.java index 2cd524b86..ac97f95bd 100644 --- a/src/main/java/org/mybatis/dynamic/sql/exception/UnrenderableWhereClauseException.java +++ b/src/main/java/org/mybatis/dynamic/sql/exception/NonRenderingWhereClauseException.java @@ -28,7 +28,7 @@ * it could cause all rows in a table to be affected by a statement - for example, * all rows could be deleted. * - *

If you intend to allow an unrenderable where clause, then configure the + *

If you intend to allow a where clause to not render, then configure the * statement to allow it, or change the global configuration. * * @see GlobalConfiguration @@ -36,6 +36,6 @@ * @since 1.4.1 * @author Jeff Butler */ -public class UnrenderableWhereClauseException extends RuntimeException { - public UnrenderableWhereClauseException() {} +public class NonRenderingWhereClauseException extends RuntimeException { + public NonRenderingWhereClauseException() {} } diff --git a/src/main/java/org/mybatis/dynamic/sql/where/WhereModel.java b/src/main/java/org/mybatis/dynamic/sql/where/WhereModel.java index 2a05b1638..5e894ec16 100644 --- a/src/main/java/org/mybatis/dynamic/sql/where/WhereModel.java +++ b/src/main/java/org/mybatis/dynamic/sql/where/WhereModel.java @@ -55,7 +55,7 @@ public List subCriteria() { } public boolean isUnrenderableClauseAllowed() { - return statementConfiguration.getUnrenderableWhereClauseAllowed(); + return statementConfiguration.isNonRenderingWhereClauseAllowed(); } /** diff --git a/src/main/java/org/mybatis/dynamic/sql/where/render/WhereRenderer.java b/src/main/java/org/mybatis/dynamic/sql/where/render/WhereRenderer.java index 9cb801e28..5208d1e8e 100644 --- a/src/main/java/org/mybatis/dynamic/sql/where/render/WhereRenderer.java +++ b/src/main/java/org/mybatis/dynamic/sql/where/render/WhereRenderer.java @@ -21,7 +21,7 @@ import java.util.stream.Collectors; import org.mybatis.dynamic.sql.SqlCriterion; -import org.mybatis.dynamic.sql.exception.UnrenderableWhereClauseException; +import org.mybatis.dynamic.sql.exception.NonRenderingWhereClauseException; import org.mybatis.dynamic.sql.render.RenderingStrategy; import org.mybatis.dynamic.sql.render.TableAliasCalculator; import org.mybatis.dynamic.sql.util.FragmentCollector; @@ -53,7 +53,7 @@ public Optional render() { if (whereClause.isPresent() || whereModel.isUnrenderableClauseAllowed()) { return whereClause; } else { - throw new UnrenderableWhereClauseException(); + throw new NonRenderingWhereClauseException(); } } diff --git a/src/test/java/examples/animal/data/AnimalDataTest.java b/src/test/java/examples/animal/data/AnimalDataTest.java index 573aa1c53..3bd85a083 100644 --- a/src/test/java/examples/animal/data/AnimalDataTest.java +++ b/src/test/java/examples/animal/data/AnimalDataTest.java @@ -651,7 +651,7 @@ void testInConditionWithEventuallyEmptyList() { SelectStatementProvider selectStatement = select(id, animalName, bodyWeight, brainWeight) .from(animalData) .where(id, isIn(null, 22, null).filter(Objects::nonNull).filter(i -> i != 22)) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -767,7 +767,7 @@ void testNotInConditionWithEventuallyEmptyList() { SelectStatementProvider selectStatement = select(id, animalName, bodyWeight, brainWeight) .from(animalData) .where(id, isNotIn(null, 22, null).filter(Objects::nonNull).filter(i -> i != 22)) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); diff --git a/src/test/java/examples/animal/data/OptionalConditionsAnimalDataTest.java b/src/test/java/examples/animal/data/OptionalConditionsAnimalDataTest.java index 74704389f..2774a9dc3 100644 --- a/src/test/java/examples/animal/data/OptionalConditionsAnimalDataTest.java +++ b/src/test/java/examples/animal/data/OptionalConditionsAnimalDataTest.java @@ -73,7 +73,7 @@ void testAllIgnored() { .from(animalData) .where(id, isGreaterThanWhenPresent(NULL_INTEGER)) // the where clause should not render .orderBy(id) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); List animals = mapper.selectMany(selectStatement); diff --git a/src/test/java/examples/animal/data/OptionalConditionsWithPredicatesAnimalDataTest.java b/src/test/java/examples/animal/data/OptionalConditionsWithPredicatesAnimalDataTest.java index 5c3841f3d..3bf1dc847 100644 --- a/src/test/java/examples/animal/data/OptionalConditionsWithPredicatesAnimalDataTest.java +++ b/src/test/java/examples/animal/data/OptionalConditionsWithPredicatesAnimalDataTest.java @@ -79,7 +79,7 @@ void testAllIgnored() { .from(animalData) .where(id, isGreaterThan(NULL_INTEGER).filter(Objects::nonNull)) // the where clause should not render .orderBy(id) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); List animals = mapper.selectMany(selectStatement); diff --git a/src/test/java/examples/complexquery/ComplexQueryTest.java b/src/test/java/examples/complexquery/ComplexQueryTest.java index aef9b9196..acbac6851 100644 --- a/src/test/java/examples/complexquery/ComplexQueryTest.java +++ b/src/test/java/examples/complexquery/ComplexQueryTest.java @@ -111,7 +111,7 @@ SelectStatementProvider search(Integer targetId, String fName, String lName) { QueryExpressionDSL.QueryExpressionWhereBuilder builder = select(id, firstName, lastName) .from(person) .where() - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)); + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)); if (targetId != null) { builder diff --git a/src/test/java/examples/emptywhere/EmptyWhereTest.java b/src/test/java/examples/emptywhere/EmptyWhereTest.java index 8f03a6d45..69807fe45 100644 --- a/src/test/java/examples/emptywhere/EmptyWhereTest.java +++ b/src/test/java/examples/emptywhere/EmptyWhereTest.java @@ -119,7 +119,7 @@ void testDeleteVariations(Variation variation) { builder.and(firstName, isEqualTo(variation.firstName).filter(Objects::nonNull)); builder.or(PersonDynamicSqlSupport.lastName, isEqualTo(variation.lastName).filter(Objects::nonNull)); - builder.configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)); + builder.configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)); DeleteStatementProvider deleteStatement = builder.build().render(RenderingStrategies.MYBATIS3); @@ -160,7 +160,7 @@ void testSelectVariations(Variation variation) { builder.and(firstName, isEqualTo(variation.firstName).filter(Objects::nonNull)); builder.or(PersonDynamicSqlSupport.lastName, isEqualTo(variation.lastName).filter(Objects::nonNull)); - builder.configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)); + builder.configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)); SelectStatementProvider selectStatement = builder.build().render(RenderingStrategies.MYBATIS3); @@ -202,7 +202,7 @@ void testJoinVariations(Variation variation) { builder.and(firstName, isEqualTo(variation.firstName).filter(Objects::nonNull)); builder.or(PersonDynamicSqlSupport.lastName, isEqualTo(variation.lastName).filter(Objects::nonNull)); - builder.configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)); + builder.configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)); SelectStatementProvider selectStatement = builder.build().render(RenderingStrategies.MYBATIS3); @@ -246,7 +246,7 @@ void testUpdateVariations(Variation variation) { builder.and(firstName, isEqualTo(variation.firstName).filter(Objects::nonNull)); builder.or(PersonDynamicSqlSupport.lastName, isEqualTo(variation.lastName).filter(Objects::nonNull)); - builder.configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)); + builder.configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)); UpdateStatementProvider updateStatement = builder.build().render(RenderingStrategies.MYBATIS3); @@ -283,7 +283,7 @@ void testWhereVariations(Variation variation) { builder.and(firstName, isEqualTo(variation.firstName).filter(Objects::nonNull)); builder.or(PersonDynamicSqlSupport.lastName, isEqualTo(variation.lastName).filter(Objects::nonNull)); - builder.configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)); + builder.configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)); WhereClauseProvider whereClause = builder.build().render(RenderingStrategies.MYBATIS3); diff --git a/src/test/java/issues/gh105/Issue105Test.java b/src/test/java/issues/gh105/Issue105Test.java index 7608553cf..211aaf6e6 100644 --- a/src/test/java/issues/gh105/Issue105Test.java +++ b/src/test/java/issues/gh105/Issue105Test.java @@ -99,7 +99,7 @@ void testFuzzyLikeBothNull() { .from(person) .where(firstName, isLike(fName).filter(Objects::nonNull).map(SearchUtils::addWildcards)) .and(lastName, isLike(lName).filter(Objects::nonNull).map(SearchUtils::addWildcards)) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -528,7 +528,7 @@ void testBetweenTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(age, isBetween(1).and((Integer) null).filter(Predicates.bothPresent()).map(i1 -> i1 + 1, i2 -> i2 + 2)) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -544,7 +544,7 @@ void testBetweenWhenPresentTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(age, isBetweenWhenPresent(1).and((Integer) null).map(i1 -> i1 + 1, i2 -> i2 + 2)) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -560,7 +560,7 @@ void testEqualTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(age, isEqualTo((Integer) null).filter(Objects::nonNull).map(i -> i + 1)) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -576,7 +576,7 @@ void testEqualWhenPresentTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(age, isEqualToWhenPresent((Integer) null).map(i -> i + 1)) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -592,7 +592,7 @@ void testGreaterThanTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(age, isGreaterThan((Integer) null).filter(Objects::nonNull).map(i -> i + 1)) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -608,7 +608,7 @@ void testGreaterThanOrEqualTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(age, isGreaterThanOrEqualTo((Integer) null).filter(Objects::nonNull).map(i -> i + 1)) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -624,7 +624,7 @@ void testGreaterThanOrEqualWhenPresentTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(age, isGreaterThanOrEqualToWhenPresent((Integer) null).map(i -> i + 1)) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -640,7 +640,7 @@ void testGreaterThanWhenPresentTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(age, isGreaterThanWhenPresent((Integer) null).map(i -> i + 1)) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -656,7 +656,7 @@ void testLessThanTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(age, isLessThan((Integer) null).filter(Objects::nonNull).map(i -> i + 1)) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -672,7 +672,7 @@ void testLessThanOrEqualTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(age, isLessThanOrEqualTo((Integer) null).filter(Objects::nonNull).map(i -> i + 1)) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -688,7 +688,7 @@ void testLessThanOrEqualWhenPresentTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(age, isLessThanOrEqualToWhenPresent((Integer) null).map(i -> i + 1)) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -704,7 +704,7 @@ void testLessThanWhenPresentTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(age, isLessThanWhenPresent((Integer) null).map(i -> i + 1)) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -720,7 +720,7 @@ void testLikeTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(firstName, isLike((String) null).filter(Objects::nonNull).map(SearchUtils::addWildcards)) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -736,7 +736,7 @@ void testLikeCaseInsensitiveTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(firstName, isLikeCaseInsensitive((String) null).filter(Objects::nonNull).map(SearchUtils::addWildcards)) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -752,7 +752,7 @@ void testLikeCaseInsensitiveWhenPresentTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(firstName, isLikeCaseInsensitiveWhenPresent((String) null).map(SearchUtils::addWildcards)) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -768,7 +768,7 @@ void testLikeWhenPresentTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(firstName, isLikeWhenPresent((String) null).map(SearchUtils::addWildcards)) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -784,7 +784,7 @@ void testNotBetweenTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(age, isNotBetween((Integer) null).and(10).filter(Predicates.bothPresent()).map(i1 -> i1 + 1, i2 -> i2 + 2)) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -800,7 +800,7 @@ void testNotBetweenWhenPresentTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(age, isNotBetweenWhenPresent(1).and((Integer) null).map(i1 -> i1 + 1, i2 -> i2 + 2)) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -816,7 +816,7 @@ void testNotEqualTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(age, isNotEqualTo((Integer) null).filter(Objects::nonNull).map(i -> i + 1)) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -832,7 +832,7 @@ void testNotEqualWhenPresentTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(age, isNotEqualToWhenPresent((Integer) null).map(i -> i + 1)) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -848,7 +848,7 @@ void testNotLikeTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(firstName, isNotLike((String) null).filter(Objects::nonNull).map(SearchUtils::addWildcards)) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -864,7 +864,7 @@ void testNotLikeCaseInsensitiveTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(firstName, isNotLikeCaseInsensitive((String) null).filter(Objects::nonNull).map(SearchUtils::addWildcards)) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -880,7 +880,7 @@ void testNotLikeCaseInsensitiveWhenPresentTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(firstName, isNotLikeCaseInsensitiveWhenPresent((String) null).map(SearchUtils::addWildcards)) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -896,7 +896,7 @@ void testNotLikeWhenPresentTransformWithNull() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where(firstName, isNotLikeWhenPresent((String) null).map(SearchUtils::addWildcards)) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); diff --git a/src/test/java/org/mybatis/dynamic/sql/StatementConfigurationTest.java b/src/test/java/org/mybatis/dynamic/sql/StatementConfigurationTest.java index beca4c7b4..dfe489977 100644 --- a/src/test/java/org/mybatis/dynamic/sql/StatementConfigurationTest.java +++ b/src/test/java/org/mybatis/dynamic/sql/StatementConfigurationTest.java @@ -29,7 +29,7 @@ import org.junit.jupiter.api.Test; import org.mybatis.dynamic.sql.delete.DeleteModel; import org.mybatis.dynamic.sql.delete.render.DeleteStatementProvider; -import org.mybatis.dynamic.sql.exception.UnrenderableWhereClauseException; +import org.mybatis.dynamic.sql.exception.NonRenderingWhereClauseException; import org.mybatis.dynamic.sql.render.RenderingStrategies; import org.mybatis.dynamic.sql.select.SelectModel; import org.mybatis.dynamic.sql.select.render.SelectStatementProvider; @@ -43,7 +43,7 @@ void testCountWhereCalledButNoCriteriaThrowsException() { .where() .build(); - assertThatExceptionOfType(UnrenderableWhereClauseException.class).isThrownBy(() -> + assertThatExceptionOfType(NonRenderingWhereClauseException.class).isThrownBy(() -> selectModel.render(RenderingStrategies.MYBATIS3) ); } @@ -52,7 +52,7 @@ void testCountWhereCalledButNoCriteriaThrowsException() { void testCountWhereCalledButNoCriteriaRequiresConfiguration() { SelectStatementProvider selectStatement = countFrom(person) .where() - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -74,7 +74,7 @@ void testDeleteWhereCalledButNoCriteriaThrowsException() { .where() .build(); - assertThatExceptionOfType(UnrenderableWhereClauseException.class).isThrownBy(() -> + assertThatExceptionOfType(NonRenderingWhereClauseException.class).isThrownBy(() -> deleteModel.render(RenderingStrategies.MYBATIS3) ); } @@ -83,7 +83,7 @@ void testDeleteWhereCalledButNoCriteriaThrowsException() { void testDeleteWhereCalledButNoCriteriaRequiresConfiguration() { DeleteStatementProvider deleteStatement = deleteFrom(person) .where() - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -106,7 +106,7 @@ void testSelectWhereCalledButNoCriteriaThrowsException() { .where() .build(); - assertThatExceptionOfType(UnrenderableWhereClauseException.class).isThrownBy(() -> + assertThatExceptionOfType(NonRenderingWhereClauseException.class).isThrownBy(() -> selectModel.render(RenderingStrategies.MYBATIS3) ); } @@ -116,7 +116,7 @@ void testSelectWhereCalledButNoCriteriaRequiresConfiguration() { SelectStatementProvider selectStatement = select(id, firstName, lastName) .from(person) .where() - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -142,7 +142,7 @@ void testUpdateWhereCalledButNoCriteriaThrowsException() { .where() .build(); - assertThatExceptionOfType(UnrenderableWhereClauseException.class).isThrownBy(() -> + assertThatExceptionOfType(NonRenderingWhereClauseException.class).isThrownBy(() -> updateModel.render(RenderingStrategies.MYBATIS3) ); } @@ -152,7 +152,7 @@ void testUpdateWhereCalledButNoCriteriaRequiresConfiguration() { UpdateStatementProvider updateStatement = update(person) .set(id).equalTo(1) .where() - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); diff --git a/src/test/java/org/mybatis/dynamic/sql/select/SelectStatementTest.java b/src/test/java/org/mybatis/dynamic/sql/select/SelectStatementTest.java index 43920fc95..70c279c57 100644 --- a/src/test/java/org/mybatis/dynamic/sql/select/SelectStatementTest.java +++ b/src/test/java/org/mybatis/dynamic/sql/select/SelectStatementTest.java @@ -398,7 +398,7 @@ void testInWhenPresentNullList() { SelectStatementProvider selectStatement = select(column1, column3) .from(table) .where(column3, isInWhenPresent((Collection) null)) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -410,7 +410,7 @@ void testInCaseInsensitiveWhenPresentNullList() { SelectStatementProvider selectStatement = select(column1, column3) .from(table) .where(column3, isInCaseInsensitiveWhenPresent((Collection) null)) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -422,7 +422,7 @@ void testNotInWhenPresentNullList() { SelectStatementProvider selectStatement = select(column1, column3) .from(table) .where(column3, isNotInWhenPresent((Collection) null)) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); @@ -434,7 +434,7 @@ void testNotInCaseInsensitiveWhenPresentNullList() { SelectStatementProvider selectStatement = select(column1, column3) .from(table) .where(column3, isNotInCaseInsensitiveWhenPresent((Collection) null)) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); diff --git a/src/test/java/org/mybatis/dynamic/sql/where/render/OptionalCriterionRenderTest.java b/src/test/java/org/mybatis/dynamic/sql/where/render/OptionalCriterionRenderTest.java index 7b0cd2821..0e0cdcc30 100644 --- a/src/test/java/org/mybatis/dynamic/sql/where/render/OptionalCriterionRenderTest.java +++ b/src/test/java/org/mybatis/dynamic/sql/where/render/OptionalCriterionRenderTest.java @@ -38,7 +38,7 @@ void testNoRenderableCriteria() { Integer nullId = null; WhereClauseProvider whereClause = where(id, isEqualToWhenPresent(nullId)) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.SPRING_NAMED_PARAMETER); @@ -53,7 +53,7 @@ void testNoRenderableCriteriaWithIf() { Integer nullId = null; WhereClauseProvider whereClause = where(id, isEqualTo(nullId).filter(Objects::nonNull)) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.SPRING_NAMED_PARAMETER); @@ -66,7 +66,7 @@ void testNoRenderableCriteriaWithIf() { @Test void testDisabledIsNull() { WhereClauseProvider whereClause = where(id, isNull().filter(() -> false)) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.SPRING_NAMED_PARAMETER); @@ -91,7 +91,7 @@ void testEnabledIsNull() { @Test void testDisabledIsNotNull() { WhereClauseProvider whereClause = where(id, isNotNull().filter(() -> false)) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.SPRING_NAMED_PARAMETER); @@ -312,7 +312,7 @@ void testCollapsingCriteriaGroup1() { WhereClauseProvider whereClause = where( group(firstName, isEqualToWhenPresent(name1)), or(lastName, isEqualToWhenPresent(name1))) - .configureStatement(c -> c.setUnrenderableWhereClauseAllowed(true)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.SPRING_NAMED_PARAMETER); diff --git a/src/test/kotlin/examples/kotlin/spring/canonical/InfixElementsTest.kt b/src/test/kotlin/examples/kotlin/spring/canonical/InfixElementsTest.kt index 4f44eb273..e14147e2d 100644 --- a/src/test/kotlin/examples/kotlin/spring/canonical/InfixElementsTest.kt +++ b/src/test/kotlin/examples/kotlin/spring/canonical/InfixElementsTest.kt @@ -101,7 +101,7 @@ open class InfixElementsTest { from(person) where { id isEqualToWhenPresent null } orderBy(id) - configureStatement { unrenderableWhereClauseAllowed = true } + configureStatement { isNonRenderingWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -136,7 +136,7 @@ open class InfixElementsTest { fun testDeleteIsNotEqualToWhenPresentNull() { val deleteStatement = deleteFrom(person) { where { id isNotEqualToWhenPresent null } - configureStatement { unrenderableWhereClauseAllowed = true } + configureStatement { isNonRenderingWhereClauseAllowed = true } } assertThat(deleteStatement.deleteStatement).isEqualTo( @@ -154,7 +154,7 @@ open class InfixElementsTest { from(person) where { id isNotEqualToWhenPresent null } orderBy(id) - configureStatement { unrenderableWhereClauseAllowed = true } + configureStatement { isNonRenderingWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -191,7 +191,7 @@ open class InfixElementsTest { from(person) where { id isGreaterThanWhenPresent null } orderBy(id) - configureStatement { unrenderableWhereClauseAllowed = true } + configureStatement { isNonRenderingWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -228,7 +228,7 @@ open class InfixElementsTest { from(person) where { id isGreaterThanOrEqualToWhenPresent null } orderBy(id) - configureStatement { unrenderableWhereClauseAllowed = true } + configureStatement { isNonRenderingWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -265,7 +265,7 @@ open class InfixElementsTest { from(person) where { id isGreaterThanWhenPresent null } orderBy(id) - configureStatement { unrenderableWhereClauseAllowed = true } + configureStatement { isNonRenderingWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -320,7 +320,7 @@ open class InfixElementsTest { from(person) where { id isLessThanOrEqualToWhenPresent null } orderBy(id) - configureStatement { unrenderableWhereClauseAllowed = true } + configureStatement { isNonRenderingWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -489,7 +489,7 @@ open class InfixElementsTest { from(person) where { id isBetweenWhenPresent null and 3 } orderBy(id) - configureStatement { unrenderableWhereClauseAllowed = true } + configureStatement { isNonRenderingWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -508,7 +508,7 @@ open class InfixElementsTest { from(person) where { id isBetweenWhenPresent 2 and null } orderBy(id) - configureStatement { unrenderableWhereClauseAllowed = true } + configureStatement { isNonRenderingWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -527,7 +527,7 @@ open class InfixElementsTest { from(person) where { id isBetweenWhenPresent null and null } orderBy(id) - configureStatement { unrenderableWhereClauseAllowed = true } + configureStatement { isNonRenderingWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -582,7 +582,7 @@ open class InfixElementsTest { from(person) where { id isNotBetweenWhenPresent null and 3 } orderBy(id) - configureStatement { unrenderableWhereClauseAllowed = true } + configureStatement { isNonRenderingWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -601,7 +601,7 @@ open class InfixElementsTest { from(person) where { id isNotBetweenWhenPresent 2 and null } orderBy(id) - configureStatement { unrenderableWhereClauseAllowed = true } + configureStatement { isNonRenderingWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -620,7 +620,7 @@ open class InfixElementsTest { from(person) where { id isNotBetweenWhenPresent null and null } orderBy(id) - configureStatement { unrenderableWhereClauseAllowed = true } + configureStatement { isNonRenderingWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -657,7 +657,7 @@ open class InfixElementsTest { from(person) where { firstName isLikeWhenPresent null } orderBy(id) - configureStatement { unrenderableWhereClauseAllowed = true } + configureStatement { isNonRenderingWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -712,7 +712,7 @@ open class InfixElementsTest { from(person) where { firstName isNotLikeWhenPresent null } orderBy(id) - configureStatement { unrenderableWhereClauseAllowed = true } + configureStatement { isNonRenderingWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -767,7 +767,7 @@ open class InfixElementsTest { from(person) where { firstName isLikeCaseInsensitiveWhenPresent null } orderBy(id) - configureStatement { unrenderableWhereClauseAllowed = true } + configureStatement { isNonRenderingWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -822,7 +822,7 @@ open class InfixElementsTest { from(person) where { firstName isNotLikeCaseInsensitiveWhenPresent null } orderBy(id) - configureStatement { unrenderableWhereClauseAllowed = true } + configureStatement { isNonRenderingWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -877,7 +877,7 @@ open class InfixElementsTest { from(person) where { firstName.isInCaseInsensitiveWhenPresent(null, null) } orderBy(id) - configureStatement { unrenderableWhereClauseAllowed = true } + configureStatement { isNonRenderingWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -932,7 +932,7 @@ open class InfixElementsTest { from(person) where { firstName.isNotInCaseInsensitiveWhenPresent(null, null) } orderBy(id) - configureStatement { unrenderableWhereClauseAllowed = true } + configureStatement { isNonRenderingWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -958,7 +958,7 @@ open class InfixElementsTest { .map { "%$it%" }) } orderBy(id) - configureStatement { unrenderableWhereClauseAllowed = true } + configureStatement { isNonRenderingWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( diff --git a/src/test/kotlin/examples/kotlin/spring/canonical/KotlinElementsTest.kt b/src/test/kotlin/examples/kotlin/spring/canonical/KotlinElementsTest.kt index 24ced760f..8027116c0 100644 --- a/src/test/kotlin/examples/kotlin/spring/canonical/KotlinElementsTest.kt +++ b/src/test/kotlin/examples/kotlin/spring/canonical/KotlinElementsTest.kt @@ -335,7 +335,7 @@ open class KotlinElementsTest { from(person) where { id (isBetweenWhenPresent(null).and(3)) } orderBy(id) - configureStatement { unrenderableWhereClauseAllowed = true } + configureStatement { isNonRenderingWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -354,7 +354,7 @@ open class KotlinElementsTest { from(person) where { id (isBetweenWhenPresent(2).and(null)) } orderBy(id) - configureStatement { unrenderableWhereClauseAllowed = true } + configureStatement { isNonRenderingWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -373,7 +373,7 @@ open class KotlinElementsTest { from(person) where { id (isBetweenWhenPresent(null).and(null)) } orderBy(id) - configureStatement { unrenderableWhereClauseAllowed = true } + configureStatement { isNonRenderingWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -428,7 +428,7 @@ open class KotlinElementsTest { from(person) where { id (isNotBetweenWhenPresent(null).and(3)) } orderBy(id) - configureStatement { unrenderableWhereClauseAllowed = true } + configureStatement { isNonRenderingWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -447,7 +447,7 @@ open class KotlinElementsTest { from(person) where { id (isNotBetweenWhenPresent(2).and(null)) } orderBy(id) - configureStatement { unrenderableWhereClauseAllowed = true } + configureStatement { isNonRenderingWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -466,7 +466,7 @@ open class KotlinElementsTest { from(person) where { id (isNotBetweenWhenPresent(null).and(null)) } orderBy(id) - configureStatement { unrenderableWhereClauseAllowed = true } + configureStatement { isNonRenderingWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -557,7 +557,7 @@ open class KotlinElementsTest { from(person) where { firstName (isInCaseInsensitiveWhenPresent(null, null)) } orderBy(id) - configureStatement { unrenderableWhereClauseAllowed = true } + configureStatement { isNonRenderingWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( @@ -612,7 +612,7 @@ open class KotlinElementsTest { from(person) where { firstName (isNotInCaseInsensitiveWhenPresent(null, null)) } orderBy(id) - configureStatement { unrenderableWhereClauseAllowed = true } + configureStatement { isNonRenderingWhereClauseAllowed = true } } assertThat(selectStatement.selectStatement).isEqualTo( From 93c91dff2a8a4ae63ef58cb6128be108d1755974 Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Wed, 24 Aug 2022 14:12:30 -0400 Subject: [PATCH 12/23] Add helpful message --- .../sql/exception/NonRenderingWhereClauseException.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/mybatis/dynamic/sql/exception/NonRenderingWhereClauseException.java b/src/main/java/org/mybatis/dynamic/sql/exception/NonRenderingWhereClauseException.java index ac97f95bd..ceec1289c 100644 --- a/src/main/java/org/mybatis/dynamic/sql/exception/NonRenderingWhereClauseException.java +++ b/src/main/java/org/mybatis/dynamic/sql/exception/NonRenderingWhereClauseException.java @@ -37,5 +37,7 @@ * @author Jeff Butler */ public class NonRenderingWhereClauseException extends RuntimeException { - public NonRenderingWhereClauseException() {} + public NonRenderingWhereClauseException() { + super("A where clause was specified, but failed to render."); //$NON-NLS-1$ + } } From 81153f4dccfcf35d3e23096ef25f6e1a8db55e8e Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Wed, 24 Aug 2022 14:13:03 -0400 Subject: [PATCH 13/23] IDEA warning removal --- src/test/java/examples/animal/data/AnimalDataTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/examples/animal/data/AnimalDataTest.java b/src/test/java/examples/animal/data/AnimalDataTest.java index 3bd85a083..e34b2a8e7 100644 --- a/src/test/java/examples/animal/data/AnimalDataTest.java +++ b/src/test/java/examples/animal/data/AnimalDataTest.java @@ -75,6 +75,7 @@ class AnimalDataTest { void setup() throws Exception { Class.forName(JDBC_DRIVER); InputStream is = getClass().getResourceAsStream("/examples/animal/data/CreateAnimalData.sql"); + assert is != null; try (Connection connection = DriverManager.getConnection(JDBC_URL, "sa", "")) { ScriptRunner sr = new ScriptRunner(connection); sr.setLogWriter(null); From d2437d4dc61fcef34f53789dbb397062d5ab7469 Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Wed, 24 Aug 2022 14:13:27 -0400 Subject: [PATCH 14/23] Make the configuration more testable --- .../configuration/GlobalConfiguration.java | 58 +++++++++++++------ .../sql/configuration/GlobalContext.java | 29 ++++++++++ .../configuration/StatementConfiguration.java | 3 +- .../GlobalConfigurationTest.java | 49 ++++++++++++++++ src/test/resources/defaultTrue.properties | 17 ++++++ src/test/resources/empty.properties | 17 ++++++ .../resources/mybatis-dynamic-sql.properties | 17 ++++++ 7 files changed, 171 insertions(+), 19 deletions(-) create mode 100644 src/main/java/org/mybatis/dynamic/sql/configuration/GlobalContext.java create mode 100644 src/test/java/org/mybatis/dynamic/sql/configuration/GlobalConfigurationTest.java create mode 100644 src/test/resources/defaultTrue.properties create mode 100644 src/test/resources/empty.properties create mode 100644 src/test/resources/mybatis-dynamic-sql.properties diff --git a/src/main/java/org/mybatis/dynamic/sql/configuration/GlobalConfiguration.java b/src/main/java/org/mybatis/dynamic/sql/configuration/GlobalConfiguration.java index edff111cd..27f27370c 100644 --- a/src/main/java/org/mybatis/dynamic/sql/configuration/GlobalConfiguration.java +++ b/src/main/java/org/mybatis/dynamic/sql/configuration/GlobalConfiguration.java @@ -19,29 +19,51 @@ import java.io.InputStream; import java.util.Properties; -// TODO - read initial value from a properties file! public class GlobalConfiguration { - private static boolean isNonRenderingWhereClauseAllowed = false; - - private GlobalConfiguration() {} - - static { - String propertyFile = "mybatis-dynamic-sql.properties"; - try (InputStream is = GlobalConfiguration.class.getResourceAsStream(propertyFile)) { - if (is != null) { - Properties p = new Properties(); - p.load(is); - String value = p.getProperty("nonRenderingWhereClauseAllowed"); - if (value != null) { - isNonRenderingWhereClauseAllowed = Boolean.parseBoolean(value); - } - } + public static final String CONFIGURATION_FILE_PROPERTY = "mybatis-dynamic-sql.configurationFile"; //$NON-NLS-1$ + private static final String DEFAULT_PROPERTY_FILE = "mybatis-dynamic-sql.properties"; //$NON-NLS-1$ + private boolean isNonRenderingWhereClauseAllowed = false; + private final Properties properties = new Properties(); + + public GlobalConfiguration() { + initialize(); + } + + private void initialize() { + initializeProperties(); + initializeNonRenderingWhereClauseAllowed(); + } + + private void initializeProperties(){ + InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(getConfigurationFileName()); + if (inputStream != null) { + loadProperties(inputStream); + } + } + + private String getConfigurationFileName() { + String property = System.getProperty(CONFIGURATION_FILE_PROPERTY); + if (property == null) { + return DEFAULT_PROPERTY_FILE; + } else { + return property; + } + } + + private void loadProperties(InputStream inputStream) { + try { + properties.load(inputStream); } catch (IOException e) { - // ignore + throw new RuntimeException(e); } } - public static boolean isIsNonRenderingWhereClauseAllowed() { + private void initializeNonRenderingWhereClauseAllowed() { + String value = properties.getProperty("nonRenderingWhereClauseAllowed", "false"); //$NON-NLS-1$ //$NON-NLS-2$ + isNonRenderingWhereClauseAllowed = Boolean.parseBoolean(value); + } + + public boolean isIsNonRenderingWhereClauseAllowed() { return isNonRenderingWhereClauseAllowed; } } diff --git a/src/main/java/org/mybatis/dynamic/sql/configuration/GlobalContext.java b/src/main/java/org/mybatis/dynamic/sql/configuration/GlobalContext.java new file mode 100644 index 000000000..9965ec2a7 --- /dev/null +++ b/src/main/java/org/mybatis/dynamic/sql/configuration/GlobalContext.java @@ -0,0 +1,29 @@ +/* + * Copyright 2016-2022 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.configuration; + +public class GlobalContext { + + private static final GlobalContext instance = new GlobalContext(); + + private final GlobalConfiguration globalConfiguration = new GlobalConfiguration(); + + private GlobalContext() {} + + public static GlobalConfiguration getConfiguration() { + return instance.globalConfiguration; + } +} diff --git a/src/main/java/org/mybatis/dynamic/sql/configuration/StatementConfiguration.java b/src/main/java/org/mybatis/dynamic/sql/configuration/StatementConfiguration.java index a121197e2..014a1001d 100644 --- a/src/main/java/org/mybatis/dynamic/sql/configuration/StatementConfiguration.java +++ b/src/main/java/org/mybatis/dynamic/sql/configuration/StatementConfiguration.java @@ -39,7 +39,8 @@ * @author Jeff Butler */ public class StatementConfiguration { - private boolean isNonRenderingWhereClauseAllowed = GlobalConfiguration.isIsNonRenderingWhereClauseAllowed(); + private boolean isNonRenderingWhereClauseAllowed = + GlobalContext.getConfiguration().isIsNonRenderingWhereClauseAllowed(); public boolean isNonRenderingWhereClauseAllowed() { return isNonRenderingWhereClauseAllowed; diff --git a/src/test/java/org/mybatis/dynamic/sql/configuration/GlobalConfigurationTest.java b/src/test/java/org/mybatis/dynamic/sql/configuration/GlobalConfigurationTest.java new file mode 100644 index 000000000..c1243054c --- /dev/null +++ b/src/test/java/org/mybatis/dynamic/sql/configuration/GlobalConfigurationTest.java @@ -0,0 +1,49 @@ +/* + * Copyright 2016-2022 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.configuration; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; + +class GlobalConfigurationTest { + @Test + void testAlternateConfigurationFileChangesDefaults() { + System.setProperty(GlobalConfiguration.CONFIGURATION_FILE_PROPERTY, "defaultTrue.properties"); + GlobalConfiguration configuration = new GlobalConfiguration(); + System.clearProperty(GlobalConfiguration.CONFIGURATION_FILE_PROPERTY); + + assertThat(configuration.isIsNonRenderingWhereClauseAllowed()).isTrue(); + } + + @Test + void testMissingPropertyUsesDefaults() { + System.setProperty(GlobalConfiguration.CONFIGURATION_FILE_PROPERTY, "empty.properties"); + GlobalConfiguration configuration = new GlobalConfiguration(); + System.clearProperty(GlobalConfiguration.CONFIGURATION_FILE_PROPERTY); + + assertThat(configuration.isIsNonRenderingWhereClauseAllowed()).isFalse(); + } + + @Test + void testMissingPropertyFileUsesDefaults() { + System.setProperty(GlobalConfiguration.CONFIGURATION_FILE_PROPERTY, "apfbsglf.properties"); + GlobalConfiguration configuration = new GlobalConfiguration(); + System.clearProperty(GlobalConfiguration.CONFIGURATION_FILE_PROPERTY); + + assertThat(configuration.isIsNonRenderingWhereClauseAllowed()).isFalse(); + } +} diff --git a/src/test/resources/defaultTrue.properties b/src/test/resources/defaultTrue.properties new file mode 100644 index 000000000..e6f3f74fa --- /dev/null +++ b/src/test/resources/defaultTrue.properties @@ -0,0 +1,17 @@ +# +# Copyright 2016-2022 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. +# + +nonRenderingWhereClauseAllowed=true diff --git a/src/test/resources/empty.properties b/src/test/resources/empty.properties new file mode 100644 index 000000000..b6782c516 --- /dev/null +++ b/src/test/resources/empty.properties @@ -0,0 +1,17 @@ +# +# Copyright 2016-2022 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. +# + +# intentionally empty for testing! diff --git a/src/test/resources/mybatis-dynamic-sql.properties b/src/test/resources/mybatis-dynamic-sql.properties new file mode 100644 index 000000000..8d5370a3d --- /dev/null +++ b/src/test/resources/mybatis-dynamic-sql.properties @@ -0,0 +1,17 @@ +# +# Copyright 2016-2022 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. +# + +nonRenderingWhereClauseAllowed=false From 7c85dda6cec82efc1f7f558cf8d5bc3879287fb2 Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Wed, 24 Aug 2022 14:54:41 -0400 Subject: [PATCH 15/23] Make the configuration more testable --- .../configuration/GlobalConfiguration.java | 12 +++-- .../GlobalConfigurationTest.java | 47 +++++++++++++++++++ 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/mybatis/dynamic/sql/configuration/GlobalConfiguration.java b/src/main/java/org/mybatis/dynamic/sql/configuration/GlobalConfiguration.java index 27f27370c..edeeb0d21 100644 --- a/src/main/java/org/mybatis/dynamic/sql/configuration/GlobalConfiguration.java +++ b/src/main/java/org/mybatis/dynamic/sql/configuration/GlobalConfiguration.java @@ -18,6 +18,8 @@ import java.io.IOException; import java.io.InputStream; import java.util.Properties; +import java.util.logging.Level; +import java.util.logging.Logger; public class GlobalConfiguration { public static final String CONFIGURATION_FILE_PROPERTY = "mybatis-dynamic-sql.configurationFile"; //$NON-NLS-1$ @@ -35,9 +37,10 @@ private void initialize() { } private void initializeProperties(){ - InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(getConfigurationFileName()); + String configFileName = getConfigurationFileName(); + InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(configFileName); if (inputStream != null) { - loadProperties(inputStream); + loadProperties(inputStream, configFileName); } } @@ -50,11 +53,12 @@ private String getConfigurationFileName() { } } - private void loadProperties(InputStream inputStream) { + void loadProperties(InputStream inputStream, String propertyFile) { try { properties.load(inputStream); } catch (IOException e) { - throw new RuntimeException(e); + Logger logger = Logger.getLogger(GlobalConfiguration.class.getName()); + logger.log(Level.SEVERE, e, () -> "IOException reading property file \"" + propertyFile + "\""); } } diff --git a/src/test/java/org/mybatis/dynamic/sql/configuration/GlobalConfigurationTest.java b/src/test/java/org/mybatis/dynamic/sql/configuration/GlobalConfigurationTest.java index c1243054c..1628e3086 100644 --- a/src/test/java/org/mybatis/dynamic/sql/configuration/GlobalConfigurationTest.java +++ b/src/test/java/org/mybatis/dynamic/sql/configuration/GlobalConfigurationTest.java @@ -17,6 +17,14 @@ import static org.assertj.core.api.Assertions.assertThat; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Handler; +import java.util.logging.LogRecord; +import java.util.logging.Logger; + import org.junit.jupiter.api.Test; class GlobalConfigurationTest { @@ -46,4 +54,43 @@ void testMissingPropertyFileUsesDefaults() { assertThat(configuration.isIsNonRenderingWhereClauseAllowed()).isFalse(); } + + @Test + void testBadPropertyFile() throws IOException { + GlobalConfiguration configuration = new GlobalConfiguration(); + InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("empty.properties"); + assert inputStream != null; + inputStream.close(); + + TestLogHandler testLogHandler = new TestLogHandler(); + Logger logger = Logger.getLogger(GlobalConfiguration.class.getName()); + // we only want to use our handler for this test, so we don't pollute the test output + logger.setUseParentHandlers(false); + logger.addHandler(testLogHandler); + + configuration.loadProperties(inputStream, "empty.properties"); + assertThat(testLogHandler.records).hasSize(1); + assertThat(testLogHandler.getRecords().get(0).getMessage()) + .isEqualTo("IOException reading property file \"empty.properties\""); + } + + public static class TestLogHandler extends Handler { + + private final List records = new ArrayList<>(); + + public List getRecords() { + return records; + } + + @Override + public void publish(LogRecord record) { + records.add(record); + } + + @Override + public void flush() {} + + @Override + public void close() {} + } } From 93af255da3b288d73ca4af3a2040109ca1806ce9 Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Wed, 24 Aug 2022 14:58:31 -0400 Subject: [PATCH 16/23] Checkstyle --- .../mybatis/dynamic/sql/configuration/GlobalConfiguration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/mybatis/dynamic/sql/configuration/GlobalConfiguration.java b/src/main/java/org/mybatis/dynamic/sql/configuration/GlobalConfiguration.java index edeeb0d21..cd6ea4dd0 100644 --- a/src/main/java/org/mybatis/dynamic/sql/configuration/GlobalConfiguration.java +++ b/src/main/java/org/mybatis/dynamic/sql/configuration/GlobalConfiguration.java @@ -36,7 +36,7 @@ private void initialize() { initializeNonRenderingWhereClauseAllowed(); } - private void initializeProperties(){ + private void initializeProperties() { String configFileName = getConfigurationFileName(); InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(configFileName); if (inputStream != null) { From cd009d6eb3ad3b9af621cea3b9e5d466115aaec4 Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Wed, 24 Aug 2022 16:46:47 -0400 Subject: [PATCH 17/23] Documentation --- CHANGELOG.md | 19 ++++++++ src/site/markdown/docs/configuration.md | 60 +++++++++++++++++++++++++ src/site/site.xml | 1 + 3 files changed, 80 insertions(+) create mode 100644 src/site/markdown/docs/configuration.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 21e7cb3aa..1cef2d1dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,22 @@ This log will detail notable changes to MyBatis Dynamic SQL. Full details are av GitHub milestone: [https://github.com/mybatis/mybatis-dynamic-sql/issues?q=milestone%3A1.4.1+](https://github.com/mybatis/mybatis-dynamic-sql/issues?q=milestone%3A1.4.1+) +### Potentially Breaking Change + +In this release we have changed the default behavior of the library in one key area. If a where clause is coded, +but fails to render because all the optional conditionals drop out of the where clause, then the library will now +throw a `NonRenderingWhereClauseException`. We have made this change out of an abundance of caution. The prior +behavior would allow generation of statements that inadvertently affected all rows in a table. + +Because of this change, we have also deprecated the "empty callback" functions in the "in" conditions. + +If you desire the prior behavior where non rendering where clauses are allowed, you can change the global configuration +of the library or - even better - change the configuration of individual statements where this behavior should be allowed. + +For examples of global and statement configuration, see the "Configuration of the Library" page. + +### Other Changes + 1. Added support for criteria groups without an initial criteria. This makes it possible to create an independent list of pre-created criteria and then add the list to a where clause. See the tests in the related pull request for usage examples. ([#462](https://github.com/mybatis/mybatis-dynamic-sql/pull/462)) @@ -15,6 +31,9 @@ GitHub milestone: [https://github.com/mybatis/mybatis-dynamic-sql/issues?q=miles 3. Updated the Kotlin DSL to use Kotlin 1.7's new "definitely non-null" types where appropriate. This helps us to more accurately represent the nullable/non-nullable expectations for API method calls. ([#496](https://github.com/mybatis/mybatis-dynamic-sql/pull/496)) +4. Added the ability to configure the library and change some default behaviors. Currently, this is limited to changing + the behavior of the library in regard to where clauses that will not render. See the new configuration page for + details. ## Release 1.4.0 - March 3, 2022 diff --git a/src/site/markdown/docs/configuration.md b/src/site/markdown/docs/configuration.md new file mode 100644 index 000000000..235718b20 --- /dev/null +++ b/src/site/markdown/docs/configuration.md @@ -0,0 +1,60 @@ +# Configuration of the Library + +Most behaviors of MyBatis Dynamic SQL are not configurable - the library does what it does. +This page will detail the behaviors that can be modified. Configuration is available with version 1.4.1 and later +of the library. + +The library can be configured globally - which will change the behavior for all statements - or each individual statement +can be configured. There are sensible defaults for all configuration values, so configuration is not strictly necessary. +If you want to change any of the default behaviors of the library, then the information on this page will help. + +Prior to version 1.4.1 of the library, there was no configurable behavior in the library. In version 1.4.1 we changed +the default behavior of the library to throw an exception if a where clause fails to render. We did this out of an +abundance of caution because the optional conditions in a where clause could lead to a statement that affected all +rows in a table (for example, a delete statement could inadvertently delete all rows in a table). If you want the library +to function as it did before version 1.4.1 where it was acceptable to have a where clause that didn't render, then you +can change the global configuration as shown below. + +## Global Configuration + +On first use the library will initialize the global configuration. The global configuration can be changed via a property +file named `mybatis-dynamic-sql.properties` in the root of the classpath. If you wish to use a different file name, +you can specify the file name as a JVM property named `mybatis-dynamic-sql.configurationFile`. Note that the global +configuration is created one time and shared for every statement in the same JVM. + +The configuration file is a standard Java properties file. The possible values are detailed in the next section. + +## Global Configuration Properties + +| Property | Default | Meaning | +|--------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| nonRenderingWhereClauseAllowed | false | If a where clause is specified, but fails to render, then the library will throw a `NonRenderingWhereClauseException` by default. If you set this value to true, then no exception will be thrown. This could cause statements to be rendered without where clauses that affect all rows in a table. | + +## Statement Configuration + +If the global configuration is not acceptable for any individual statement, you can also configure the statement in the +DSL. Consider the following statement: + +```java +DeleteStatementProvider deleteStatement = deleteFrom(animalData) + .where(id, isNotIn(null, 22, null).filter(Objects::nonNull).filter(i -> i != 22)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) + .build() + .render(RenderingStrategies.MYBATIS3); +``` + +In this case, the `isNotIn` condition has filters that will remove all values from the condition. In that case, the +condition will not render and, subsequently, the where clause will not render. This means that the generated delete +statement would delete all rows in the table. By default, the global configuration will block this statement from +rendering and throw a `NonRenderingWhereClauseException`. If for some reason you would like to allow a statement +like this to be rendered, then you can allow it as shown above with the `configureStatement` method. + +The Kotlin DSL contains the same function: + +```kotlin +val deleteStatement = deleteFrom(person) { + where { id isNotEqualToWhenPresent null } + configureStatement { isNonRenderingWhereClauseAllowed = true } +} +``` + diff --git a/src/site/site.xml b/src/site/site.xml index 88110419d..d7cab962a 100644 --- a/src/site/site.xml +++ b/src/site/site.xml @@ -37,6 +37,7 @@ + From e31f68f794e731c95931f8bb6e44395a6f32f8cb Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Wed, 24 Aug 2022 17:27:10 -0400 Subject: [PATCH 18/23] Deprecate the "empty list" methods The new statement configuration functionality is better and more flexible --- .../sql/AbstractListValueCondition.java | 21 ++++++++++++++++++- .../dynamic/sql/where/condition/IsIn.java | 17 +++++++++++++++ .../where/condition/IsInCaseInsensitive.java | 17 +++++++++++++++ .../dynamic/sql/where/condition/IsNotIn.java | 18 ++++++++++++++++ .../condition/IsNotInCaseInsensitive.java | 17 +++++++++++++++ 5 files changed, 89 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/mybatis/dynamic/sql/AbstractListValueCondition.java b/src/main/java/org/mybatis/dynamic/sql/AbstractListValueCondition.java index 148865302..b6f3e64d3 100644 --- a/src/main/java/org/mybatis/dynamic/sql/AbstractListValueCondition.java +++ b/src/main/java/org/mybatis/dynamic/sql/AbstractListValueCondition.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2021 the original author or authors. + * Copyright 2016-2022 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. @@ -26,12 +26,23 @@ public abstract class AbstractListValueCondition implements VisitableCondition { protected final Collection values; + + /** + * @deprecated in favor of the statement configuration functions + */ + @Deprecated protected final Callback emptyCallback; protected AbstractListValueCondition(Collection values) { this(values, () -> { }); } + /** + * @deprecated in favor of the statement configuration functions + * @param values values + * @param emptyCallback empty callback + */ + @Deprecated protected AbstractListValueCondition(Collection values, Callback emptyCallback) { this.values = Objects.requireNonNull(values); this.emptyCallback = Objects.requireNonNull(emptyCallback); @@ -96,6 +107,14 @@ protected > S mapSupport(Function filter(Predicate predicate); + /** + * Specifies a callback function to be called if the value list is empty when rendered. + * + * @deprecated in favor of the statement configuration functions + * @param callback a callback function - typically throws an exception to block the statement from executing + * @return this condition + */ + @Deprecated public abstract AbstractListValueCondition withListEmptyCallback(Callback callback); public abstract String renderCondition(String columnName, Stream placeholders); diff --git a/src/main/java/org/mybatis/dynamic/sql/where/condition/IsIn.java b/src/main/java/org/mybatis/dynamic/sql/where/condition/IsIn.java index e55dd8932..c579f57b8 100644 --- a/src/main/java/org/mybatis/dynamic/sql/where/condition/IsIn.java +++ b/src/main/java/org/mybatis/dynamic/sql/where/condition/IsIn.java @@ -38,6 +38,11 @@ public static IsIn empty() { return t; } + /** + * @deprecated in favor of the statement configuration functions + * @return a new empty condition + */ + @Deprecated private IsIn emptyWithCallBack() { return new IsIn<>(Collections.emptyList(), emptyCallback); } @@ -46,6 +51,12 @@ protected IsIn(Collection values) { super(values); } + /** + * @deprecated in favor of the statement configuration functions + * @param values values + * @param emptyCallback empty callback + */ + @Deprecated protected IsIn(Collection values, Callback emptyCallback) { super(values, emptyCallback); } @@ -56,6 +67,12 @@ public String renderCondition(String columnName, Stream placeholders) { + placeholders.collect(Collectors.joining(",", "in (", ")")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } + /** + * @deprecated in favor of the statement configuration functions + * @param callback a callback function - typically throws an exception to block the statement from executing + * @return this condition + */ + @Deprecated @Override public IsIn withListEmptyCallback(Callback callback) { return new IsIn<>(values, callback); diff --git a/src/main/java/org/mybatis/dynamic/sql/where/condition/IsInCaseInsensitive.java b/src/main/java/org/mybatis/dynamic/sql/where/condition/IsInCaseInsensitive.java index 368ecc8bc..ddbf948c4 100644 --- a/src/main/java/org/mybatis/dynamic/sql/where/condition/IsInCaseInsensitive.java +++ b/src/main/java/org/mybatis/dynamic/sql/where/condition/IsInCaseInsensitive.java @@ -34,6 +34,11 @@ public static IsInCaseInsensitive empty() { return EMPTY; } + /** + * @deprecated in favor of the statement configuration functions + * @return a new empty condition + */ + @Deprecated private IsInCaseInsensitive emptyWithCallback() { return new IsInCaseInsensitive(Collections.emptyList(), emptyCallback); } @@ -42,6 +47,12 @@ protected IsInCaseInsensitive(Collection values) { super(values); } + /** + * @deprecated in favor of the statement configuration functions + * @param values values + * @param emptyCallback empty callback + */ + @Deprecated protected IsInCaseInsensitive(Collection values, Callback emptyCallback) { super(values, emptyCallback); } @@ -53,6 +64,12 @@ public String renderCondition(String columnName, Stream placeholders) { Collectors.joining(",", "in (", ")")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } + /** + * @deprecated in favor of the statement configuration functions + * @param callback a callback function - typically throws an exception to block the statement from executing + * @return this condition + */ + @Deprecated @Override public IsInCaseInsensitive withListEmptyCallback(Callback callback) { return new IsInCaseInsensitive(values, callback); diff --git a/src/main/java/org/mybatis/dynamic/sql/where/condition/IsNotIn.java b/src/main/java/org/mybatis/dynamic/sql/where/condition/IsNotIn.java index 4a2f27546..44102bf9f 100644 --- a/src/main/java/org/mybatis/dynamic/sql/where/condition/IsNotIn.java +++ b/src/main/java/org/mybatis/dynamic/sql/where/condition/IsNotIn.java @@ -38,6 +38,11 @@ public static IsNotIn empty() { return t; } + /** + * @deprecated in favor of the statement configuration functions + * @return a new empty condition + */ + @Deprecated private IsNotIn emptyWithCallback() { return new IsNotIn<>(Collections.emptyList(), emptyCallback); } @@ -46,6 +51,12 @@ protected IsNotIn(Collection values) { super(values); } + /** + * @deprecated in favor of the statement configuration functions + * @param values values + * @param emptyCallback empty callback + */ + @Deprecated protected IsNotIn(Collection values, Callback emptyCallback) { super(values, emptyCallback); } @@ -57,6 +68,13 @@ public String renderCondition(String columnName, Stream placeholders) { Collectors.joining(",", "not in (", ")")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } + /** + * + * @deprecated in favor of the statement configuration functions + * @param callback a callback function - typically throws an exception to block the statement from executing + * @return this condition + */ + @Deprecated @Override public IsNotIn withListEmptyCallback(Callback callback) { return new IsNotIn<>(values, callback); diff --git a/src/main/java/org/mybatis/dynamic/sql/where/condition/IsNotInCaseInsensitive.java b/src/main/java/org/mybatis/dynamic/sql/where/condition/IsNotInCaseInsensitive.java index 211493090..df1735ed2 100644 --- a/src/main/java/org/mybatis/dynamic/sql/where/condition/IsNotInCaseInsensitive.java +++ b/src/main/java/org/mybatis/dynamic/sql/where/condition/IsNotInCaseInsensitive.java @@ -34,6 +34,11 @@ public static IsNotInCaseInsensitive empty() { return EMPTY; } + /** + * @deprecated in favor of the statement configuration functions + * @return a new empty condition + */ + @Deprecated private IsNotInCaseInsensitive emptyWithCallback() { return new IsNotInCaseInsensitive(Collections.emptyList(), emptyCallback); } @@ -42,6 +47,12 @@ protected IsNotInCaseInsensitive(Collection values) { super(values); } + /** + * @deprecated in favor of the statement configuration functions + * @param values values + * @param emptyCallback empty callback + */ + @Deprecated protected IsNotInCaseInsensitive(Collection values, Callback emptyCallback) { super(values, emptyCallback); } @@ -53,6 +64,12 @@ public String renderCondition(String columnName, Stream placeholders) { Collectors.joining(",", "not in (", ")")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } + /** + * @deprecated in favor of the statement configuration functions + * @param callback a callback function - typically throws an exception to block the statement from executing + * @return this condition + */ + @Deprecated @Override public IsNotInCaseInsensitive withListEmptyCallback(Callback callback) { return new IsNotInCaseInsensitive(values, callback); From 5a68a75364ac87660a4b5c442b6506a24e5a65b1 Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Thu, 25 Aug 2022 10:12:15 -0400 Subject: [PATCH 19/23] Kotlin DSL statement configuration should not call where() This could cause an exception if no where clause is specified --- .../mybatis/dynamic/sql/delete/DeleteDSL.java | 10 +++++- .../select/AbstractQueryExpressionDSL.java | 2 +- .../mybatis/dynamic/sql/select/CountDSL.java | 7 ++++ .../sql/select/QueryExpressionDSL.java | 12 +++++-- .../mybatis/dynamic/sql/update/UpdateDSL.java | 10 +++++- .../sql/where/AbstractWhereSupport.java | 4 ++- .../sql/util/kotlin/KotlinBaseBuilders.kt | 4 +-- .../java/examples/joins/JoinMapperTest.java | 1 + .../spring/canonical/InfixElementsTest.kt | 35 +++++++++++++++++++ 9 files changed, 76 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/mybatis/dynamic/sql/delete/DeleteDSL.java b/src/main/java/org/mybatis/dynamic/sql/delete/DeleteDSL.java index 7eb462a0d..8b59ff8e1 100644 --- a/src/main/java/org/mybatis/dynamic/sql/delete/DeleteDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/delete/DeleteDSL.java @@ -16,6 +16,7 @@ package org.mybatis.dynamic.sql.delete; import java.util.Objects; +import java.util.function.Consumer; import java.util.function.Function; import org.jetbrains.annotations.NotNull; @@ -26,7 +27,8 @@ import org.mybatis.dynamic.sql.where.AbstractWhereSupport; import org.mybatis.dynamic.sql.where.WhereModel; -public class DeleteDSL extends AbstractWhereSupport.DeleteWhereBuilder> implements Buildable { +public class DeleteDSL extends AbstractWhereSupport.DeleteWhereBuilder, DeleteDSL> + implements Buildable { private final Function adapterFunction; private final SqlTable table; @@ -66,6 +68,12 @@ public R build() { return adapterFunction.apply(deleteModelBuilder.build()); } + @Override + public DeleteDSL configureStatement(Consumer consumer) { + consumer.accept(statementConfiguration); + return this; + } + public static DeleteDSL deleteFrom(Function adapterFunction, SqlTable table, String tableAlias) { return new DeleteDSL<>(table, tableAlias, adapterFunction); 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 1cabb6300..c5130ddac 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/AbstractQueryExpressionDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/AbstractQueryExpressionDSL.java @@ -38,7 +38,7 @@ public abstract class AbstractQueryExpressionDSL, T extends AbstractQueryExpressionDSL> - extends AbstractWhereSupport { + extends AbstractWhereSupport { private final List joinSpecificationBuilders = new ArrayList<>(); private final Map tableAliases = new HashMap<>(); diff --git a/src/main/java/org/mybatis/dynamic/sql/select/CountDSL.java b/src/main/java/org/mybatis/dynamic/sql/select/CountDSL.java index dc495fb2a..139373453 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/CountDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/CountDSL.java @@ -16,6 +16,7 @@ package org.mybatis.dynamic.sql.select; import java.util.Objects; +import java.util.function.Consumer; import java.util.function.Function; import org.jetbrains.annotations.NotNull; @@ -64,6 +65,12 @@ public R build() { return adapterFunction.apply(buildModel()); } + @Override + public CountDSL configureStatement(Consumer consumer) { + consumer.accept(statementConfiguration); + return this; + } + private SelectModel buildModel() { QueryExpressionModel.Builder b = new QueryExpressionModel.Builder() .withSelectColumn(countColumn) diff --git a/src/main/java/org/mybatis/dynamic/sql/select/QueryExpressionDSL.java b/src/main/java/org/mybatis/dynamic/sql/select/QueryExpressionDSL.java index 44e349c38..8f379bb70 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/QueryExpressionDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/QueryExpressionDSL.java @@ -33,14 +33,13 @@ import org.mybatis.dynamic.sql.select.join.JoinSpecification; import org.mybatis.dynamic.sql.select.join.JoinType; import org.mybatis.dynamic.sql.util.Buildable; -import org.mybatis.dynamic.sql.util.ConfigurableStatement; import org.mybatis.dynamic.sql.where.AbstractWhereDSL; import org.mybatis.dynamic.sql.where.AbstractWhereSupport; import org.mybatis.dynamic.sql.where.WhereModel; public class QueryExpressionDSL extends AbstractQueryExpressionDSL.QueryExpressionWhereBuilder, QueryExpressionDSL> - implements Buildable, ConfigurableStatement> { + implements Buildable { private final String connector; private final SelectDSL selectDSL; @@ -332,7 +331,8 @@ public JoinSpecificationFinisher on(BasicColumn joinColumn, JoinCondition onJoin } } - public class JoinSpecificationFinisher extends AbstractWhereSupport + public class JoinSpecificationFinisher + extends AbstractWhereSupport implements Buildable { private final JoinSpecification.Builder joinSpecificationBuilder; @@ -373,6 +373,12 @@ public R build() { return QueryExpressionDSL.this.build(); } + @Override + public JoinSpecificationFinisher configureStatement(Consumer consumer) { + consumer.accept(statementConfiguration); + return this; + } + @Override public QueryExpressionWhereBuilder where() { return QueryExpressionDSL.this.where(); diff --git a/src/main/java/org/mybatis/dynamic/sql/update/UpdateDSL.java b/src/main/java/org/mybatis/dynamic/sql/update/UpdateDSL.java index b3512450c..8f79be1f0 100644 --- a/src/main/java/org/mybatis/dynamic/sql/update/UpdateDSL.java +++ b/src/main/java/org/mybatis/dynamic/sql/update/UpdateDSL.java @@ -18,6 +18,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; @@ -41,7 +42,8 @@ import org.mybatis.dynamic.sql.where.AbstractWhereSupport; import org.mybatis.dynamic.sql.where.WhereModel; -public class UpdateDSL extends AbstractWhereSupport.UpdateWhereBuilder> implements Buildable { +public class UpdateDSL extends AbstractWhereSupport.UpdateWhereBuilder, UpdateDSL> + implements Buildable { private final Function adapterFunction; private final List columnMappings = new ArrayList<>(); @@ -89,6 +91,12 @@ public R build() { return adapterFunction.apply(updateModelBuilder.build()); } + @Override + public UpdateDSL configureStatement(Consumer consumer) { + consumer.accept(statementConfiguration); + return this; + } + public static UpdateDSL update(Function adapterFunction, SqlTable table, String tableAlias) { return new UpdateDSL<>(table, tableAlias, adapterFunction); } diff --git a/src/main/java/org/mybatis/dynamic/sql/where/AbstractWhereSupport.java b/src/main/java/org/mybatis/dynamic/sql/where/AbstractWhereSupport.java index 29384e153..ac30a8c95 100644 --- a/src/main/java/org/mybatis/dynamic/sql/where/AbstractWhereSupport.java +++ b/src/main/java/org/mybatis/dynamic/sql/where/AbstractWhereSupport.java @@ -24,6 +24,7 @@ import org.mybatis.dynamic.sql.ExistsPredicate; import org.mybatis.dynamic.sql.SqlCriterion; import org.mybatis.dynamic.sql.VisitableCondition; +import org.mybatis.dynamic.sql.util.ConfigurableStatement; /** * Base class for DSLs that support where clauses - which is every DSL except Insert. @@ -33,7 +34,8 @@ * * @param the implementation of the Where DSL customized for a particular SQL statement. */ -public abstract class AbstractWhereSupport> { +public abstract class AbstractWhereSupport, D extends AbstractWhereSupport> + implements ConfigurableStatement { public abstract W where(); diff --git a/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/KotlinBaseBuilders.kt b/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/KotlinBaseBuilders.kt index fe868ac75..9a8c86210 100644 --- a/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/KotlinBaseBuilders.kt +++ b/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/KotlinBaseBuilders.kt @@ -38,10 +38,10 @@ fun WhereApplier.andThen(after: WhereApplier): WhereApplier = { @MyBatisDslMarker @Suppress("TooManyFunctions") -abstract class KotlinBaseBuilder> { +abstract class KotlinBaseBuilder> { fun configureStatement(c: StatementConfiguration.() -> Unit) { - getDsl().where().configureStatement(c) + getDsl().configureStatement(c) } fun where(criteria: GroupingCriteriaReceiver): Unit = diff --git a/src/test/java/examples/joins/JoinMapperTest.java b/src/test/java/examples/joins/JoinMapperTest.java index a8e599350..61118911f 100644 --- a/src/test/java/examples/joins/JoinMapperTest.java +++ b/src/test/java/examples/joins/JoinMapperTest.java @@ -163,6 +163,7 @@ void testCompoundJoin2() { SelectStatementProvider selectStatement = select(orderMaster.orderId, orderDate, orderDetail.lineNumber, orderDetail.description, orderDetail.quantity) .from(orderMaster, "om") .join(orderDetail, "od").on(orderMaster.orderId, equalTo(orderDetail.orderId)) + .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .and(orderMaster.orderId, equalTo(orderDetail.orderId)) .build() .render(RenderingStrategies.MYBATIS3); diff --git a/src/test/kotlin/examples/kotlin/spring/canonical/InfixElementsTest.kt b/src/test/kotlin/examples/kotlin/spring/canonical/InfixElementsTest.kt index e14147e2d..0e5593550 100644 --- a/src/test/kotlin/examples/kotlin/spring/canonical/InfixElementsTest.kt +++ b/src/test/kotlin/examples/kotlin/spring/canonical/InfixElementsTest.kt @@ -28,11 +28,14 @@ import org.mybatis.dynamic.sql.util.kotlin.KInvalidSQLException import org.mybatis.dynamic.sql.util.kotlin.elements.isLike import org.mybatis.dynamic.sql.util.kotlin.elements.stringConstant import org.mybatis.dynamic.sql.util.kotlin.elements.upper +import org.mybatis.dynamic.sql.util.kotlin.mybatis3.count +import org.mybatis.dynamic.sql.util.kotlin.spring.countFrom import org.mybatis.dynamic.sql.util.kotlin.spring.delete import org.mybatis.dynamic.sql.util.kotlin.spring.deleteFrom import org.mybatis.dynamic.sql.util.kotlin.spring.select import org.mybatis.dynamic.sql.util.kotlin.spring.selectList import org.mybatis.dynamic.sql.util.kotlin.spring.selectOne +import org.mybatis.dynamic.sql.util.kotlin.spring.update import org.springframework.beans.factory.annotation.Autowired import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate import org.springframework.test.context.junit.jupiter.SpringJUnitConfig @@ -1229,4 +1232,36 @@ open class InfixElementsTest { assertThat(rows).hasSize(2) assertThat(rows[0]).isEqualTo("Pebbles") } + + @Test + fun testUpdate() { + val updateStatement = update(person) { + set(id) equalTo 1 + // following should have no impact - where clause not specified + configureStatement { isNonRenderingWhereClauseAllowed = false } + } + + assertThat(updateStatement.updateStatement).isEqualTo("update Person set id = :p1") + } + + @Test + fun testCount() { + val selectStatement = countFrom(person) { + // following should have no impact - where clause not specified + configureStatement { isNonRenderingWhereClauseAllowed = false } + } + + assertThat(selectStatement.selectStatement).isEqualTo("select count(*) from Person") + } + + @Test + fun testQueryExpression() { + val selectStatement = select(id) { + from(person) + // following should have no impact - where clause not specified + configureStatement { isNonRenderingWhereClauseAllowed = false } + } + + assertThat(selectStatement.selectStatement).isEqualTo("select id from Person") + } } From e8876ade8c383f0e9de26539ba4a343b612d430f Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Thu, 25 Aug 2022 10:27:23 -0400 Subject: [PATCH 20/23] Update docs --- CHANGELOG.md | 10 +++++++--- src/site/markdown/docs/configuration.md | 22 ++++++++++------------ 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1cef2d1dc..a3aaa9bbd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,11 @@ but fails to render because all the optional conditionals drop out of the where throw a `NonRenderingWhereClauseException`. We have made this change out of an abundance of caution. The prior behavior would allow generation of statements that inadvertently affected all rows in a table. -Because of this change, we have also deprecated the "empty callback" functions in the "in" conditions. +We have also deprecated the "empty callback" functions in the "in" conditions in favor of this new configuration +strategy. The "empty callback" methods were effective for "in" conditions that failed to render, but they offered +no help for other conditions that failed to render, or if all conditions fail to render - which is arguably a more +dangerous outcome. If you were using any of these methods, you should remove the calls to those methods and catch the +new `NonRenderingWhereClauseException`. If you desire the prior behavior where non rendering where clauses are allowed, you can change the global configuration of the library or - even better - change the configuration of individual statements where this behavior should be allowed. @@ -32,8 +36,8 @@ For examples of global and statement configuration, see the "Configuration of th accurately represent the nullable/non-nullable expectations for API method calls. ([#496](https://github.com/mybatis/mybatis-dynamic-sql/pull/496)) 4. Added the ability to configure the library and change some default behaviors. Currently, this is limited to changing - the behavior of the library in regard to where clauses that will not render. See the new configuration page for - details. + the behavior of the library in regard to where clauses that will not render. See the "Configuration of the Library" + page for details. ## Release 1.4.0 - March 3, 2022 diff --git a/src/site/markdown/docs/configuration.md b/src/site/markdown/docs/configuration.md index 235718b20..4796d387d 100644 --- a/src/site/markdown/docs/configuration.md +++ b/src/site/markdown/docs/configuration.md @@ -1,8 +1,7 @@ # Configuration of the Library -Most behaviors of MyBatis Dynamic SQL are not configurable - the library does what it does. -This page will detail the behaviors that can be modified. Configuration is available with version 1.4.1 and later -of the library. +This page will detail the behaviors of MyBatis Dynamic SQL that can be modified. +Configuration is available with version 1.4.1 and later of the library. The library can be configured globally - which will change the behavior for all statements - or each individual statement can be configured. There are sensible defaults for all configuration values, so configuration is not strictly necessary. @@ -12,12 +11,11 @@ Prior to version 1.4.1 of the library, there was no configurable behavior in the the default behavior of the library to throw an exception if a where clause fails to render. We did this out of an abundance of caution because the optional conditions in a where clause could lead to a statement that affected all rows in a table (for example, a delete statement could inadvertently delete all rows in a table). If you want the library -to function as it did before version 1.4.1 where it was acceptable to have a where clause that didn't render, then you -can change the global configuration as shown below. +to function as it did before version 1.4.1 , then you can change the global configuration as shown below. ## Global Configuration -On first use the library will initialize the global configuration. The global configuration can be changed via a property +On first use the library will initialize the global configuration. The global configuration can be specified via a property file named `mybatis-dynamic-sql.properties` in the root of the classpath. If you wish to use a different file name, you can specify the file name as a JVM property named `mybatis-dynamic-sql.configurationFile`. Note that the global configuration is created one time and shared for every statement in the same JVM. @@ -26,9 +24,9 @@ The configuration file is a standard Java properties file. The possible values a ## Global Configuration Properties -| Property | Default | Meaning | -|--------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| nonRenderingWhereClauseAllowed | false | If a where clause is specified, but fails to render, then the library will throw a `NonRenderingWhereClauseException` by default. If you set this value to true, then no exception will be thrown. This could cause statements to be rendered without where clauses that affect all rows in a table. | +| Property | Default | Meaning | +|--------------------------------|---------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| nonRenderingWhereClauseAllowed | false | If a where clause is specified, but fails to render, then the library will throw a `NonRenderingWhereClauseException` by default. If you set this value to true, then no exception will be thrown. This could enable statements to be rendered without where clauses that affect all rows in a table. | ## Statement Configuration @@ -37,13 +35,13 @@ DSL. Consider the following statement: ```java DeleteStatementProvider deleteStatement = deleteFrom(animalData) - .where(id, isNotIn(null, 22, null).filter(Objects::nonNull).filter(i -> i != 22)) + .where(id, isIn(null, 22, null).filter(Objects::nonNull).filter(i -> i != 22)) .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true)) .build() .render(RenderingStrategies.MYBATIS3); ``` -In this case, the `isNotIn` condition has filters that will remove all values from the condition. In that case, the +In this case, the `isIn` condition has filters that will remove all values from the condition. In that case, the condition will not render and, subsequently, the where clause will not render. This means that the generated delete statement would delete all rows in the table. By default, the global configuration will block this statement from rendering and throw a `NonRenderingWhereClauseException`. If for some reason you would like to allow a statement @@ -53,7 +51,7 @@ The Kotlin DSL contains the same function: ```kotlin val deleteStatement = deleteFrom(person) { - where { id isNotEqualToWhenPresent null } + where { id isEqualToWhenPresent null } configureStatement { isNonRenderingWhereClauseAllowed = true } } ``` From fda6dd64aa4a62e03858705840bd3b022db82648 Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Thu, 25 Aug 2022 10:59:14 -0400 Subject: [PATCH 21/23] Update docs --- src/site/markdown/docs/conditions.md | 41 ++++++++++++---------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/src/site/markdown/docs/conditions.md b/src/site/markdown/docs/conditions.md index cea2e2885..4947c39eb 100644 --- a/src/site/markdown/docs/conditions.md +++ b/src/site/markdown/docs/conditions.md @@ -200,29 +200,6 @@ of the *values* of the condition. The library comes with functions that will fil case String values to enable case insensitive queries. There are extension points to add additional filtering and mapping if you so desire. -We think it is a good thing that the library will not render invalid SQL. An "in" condition will always be dropped from -rendering if the list of values is empty. But there is some danger with this stance. Because the condition could be -dropped from the rendered SQL, more rows could be impacted than expected if the list ends up empty for whatever reason. -Our recommended solution is to make sure that you validate list values - especially if they are coming from direct user -input. Another option is to take some action when the list is empty. This can be especially helpful when you are -applying filters to the value list or using one of the built-in "when present" conditions. In that case, it is -possible that the list of values could end up empty after a validation check. - -The "In" conditions support a callback that will be invoked when the value list is empty and just before the statement -is rendered. You could use the callback to create a condition that will throw an exception when the list is empty. -For example: - -```java - private static IsIn isInRequired(Collection values) { - return IsIn.of(values).withListEmptyCallback(() -> { throw new RuntimeException("In values cannot be empty"); } ); - } - - // Alternatively, there is a convenience method in the Callback interface - private static IsIn isInRequired(Collection values) { - return IsIn.of(values).withListEmptyCallback(Callback.exceptionThrowingCallback("In values cannot be empty")); - } -``` - The following table shows the different supplied In conditions and how they will render for different sets of inputs. The table assumes the following types of input: @@ -286,3 +263,21 @@ Then the condition could be used in a query as follows: .build() .render(RenderingStrategies.MYBATIS3); ``` + +## Potential for Non Rendering Where Clauses + +An "in" condition will always be dropped from rendering if the list of values is empty. Other conditions could be +dropped from a where clause due to filtering. If all conditions fail to render, then the entire where clause will be +dropped from the rendered SQL. In general, we think it is a good thing that the library will not render invalid SQL. +But this stance does present a danger - if a where clause is dropped from the rendered SQL, then the statement could +end up impacting all rows in a table. For example, a delete statement could inadvertently delete all rows in a table. + +By default, and out of an abundance of caution, the library will not allow a statement to render if the entire where +clause will be dropped. If a where clause is coded, but fails to render, then the library will throw a +`NonRenderingWhereClauseException` by default. + +If no where clause is coded in a statement, then we assume the statement is intended to affect all rows in a table. +In that case no exception will be thrown. + +This behavior can be modified through configuration - either globally for the entire library, or for each statement +individually. See the "Configuration of the Library" page for details on configuration options. From f67bc5dab3b9b1ee167c60710cdcb6c9b5f7bcd8 Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Thu, 25 Aug 2022 11:03:49 -0400 Subject: [PATCH 22/23] Deprecate the callback interface in favor of configuration functions --- src/main/java/org/mybatis/dynamic/sql/Callback.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/mybatis/dynamic/sql/Callback.java b/src/main/java/org/mybatis/dynamic/sql/Callback.java index 2c5f07704..4e38c2864 100644 --- a/src/main/java/org/mybatis/dynamic/sql/Callback.java +++ b/src/main/java/org/mybatis/dynamic/sql/Callback.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2022 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. @@ -17,6 +17,10 @@ import java.util.function.Function; +/** + * @deprecated in favor of the new statement configuration functionality + */ +@Deprecated @FunctionalInterface public interface Callback { void call(); From 21e45e7349ae5722d144e4b3d2be6e006f2956cc Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Thu, 25 Aug 2022 11:36:49 -0400 Subject: [PATCH 23/23] Add PR Number to Changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a3aaa9bbd..86e260063 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,7 +37,7 @@ For examples of global and statement configuration, see the "Configuration of th ([#496](https://github.com/mybatis/mybatis-dynamic-sql/pull/496)) 4. Added the ability to configure the library and change some default behaviors. Currently, this is limited to changing the behavior of the library in regard to where clauses that will not render. See the "Configuration of the Library" - page for details. + page for details. ([#515](https://github.com/mybatis/mybatis-dynamic-sql/pull/515)) ## Release 1.4.0 - March 3, 2022