diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 5a6947c02..e89bd81b6 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -9,7 +9,7 @@ jobs: matrix: cache: [maven] distribution: [temurin] - java: [17, 21, 22, 23-ea] + java: [17, 21, 23, 24-ea] os: [ubuntu-latest] fail-fast: false max-parallel: 4 diff --git a/src/main/java/org/mybatis/dynamic/sql/delete/DeleteModel.java b/src/main/java/org/mybatis/dynamic/sql/delete/DeleteModel.java index 015f9823c..4519b1002 100644 --- a/src/main/java/org/mybatis/dynamic/sql/delete/DeleteModel.java +++ b/src/main/java/org/mybatis/dynamic/sql/delete/DeleteModel.java @@ -23,8 +23,8 @@ import org.mybatis.dynamic.sql.common.CommonBuilder; import org.mybatis.dynamic.sql.common.OrderByModel; import org.mybatis.dynamic.sql.configuration.StatementConfiguration; +import org.mybatis.dynamic.sql.delete.render.DeleteRenderer; import org.mybatis.dynamic.sql.delete.render.DeleteStatementProvider; -import org.mybatis.dynamic.sql.render.RendererFactory; import org.mybatis.dynamic.sql.render.RenderingStrategy; import org.mybatis.dynamic.sql.where.EmbeddedWhereModel; @@ -65,10 +65,16 @@ public Optional orderByModel() { return Optional.ofNullable(orderByModel); } + public StatementConfiguration statementConfiguration() { + return statementConfiguration; + } + @NotNull public DeleteStatementProvider render(RenderingStrategy renderingStrategy) { - return RendererFactory.createDeleteRenderer(this, statementConfiguration) - .render(renderingStrategy); + return DeleteRenderer.withDeleteModel(this) + .withRenderingStrategy(renderingStrategy) + .build() + .render(); } public static Builder withTable(SqlTable table) { diff --git a/src/main/java/org/mybatis/dynamic/sql/delete/render/DefaultDeleteStatementProvider.java b/src/main/java/org/mybatis/dynamic/sql/delete/render/DefaultDeleteStatementProvider.java index 89b72333b..ef2ade7f0 100644 --- a/src/main/java/org/mybatis/dynamic/sql/delete/render/DefaultDeleteStatementProvider.java +++ b/src/main/java/org/mybatis/dynamic/sql/delete/render/DefaultDeleteStatementProvider.java @@ -25,7 +25,7 @@ public class DefaultDeleteStatementProvider implements DeleteStatementProvider { private DefaultDeleteStatementProvider(Builder builder) { deleteStatement = Objects.requireNonNull(builder.deleteStatement); - parameters = Objects.requireNonNull(builder.parameters); + parameters = builder.parameters; } @Override diff --git a/src/main/java/org/mybatis/dynamic/sql/delete/render/DeleteRenderer.java b/src/main/java/org/mybatis/dynamic/sql/delete/render/DeleteRenderer.java index fa4cd0d28..7b3dbfc97 100644 --- a/src/main/java/org/mybatis/dynamic/sql/delete/render/DeleteRenderer.java +++ b/src/main/java/org/mybatis/dynamic/sql/delete/render/DeleteRenderer.java @@ -21,7 +21,6 @@ import org.mybatis.dynamic.sql.common.OrderByModel; import org.mybatis.dynamic.sql.common.OrderByRenderer; -import org.mybatis.dynamic.sql.configuration.StatementConfiguration; import org.mybatis.dynamic.sql.delete.DeleteModel; import org.mybatis.dynamic.sql.render.ExplicitTableAliasCalculator; import org.mybatis.dynamic.sql.render.RenderedParameterInfo; @@ -44,7 +43,7 @@ private DeleteRenderer(Builder builder) { renderingContext = RenderingContext .withRenderingStrategy(Objects.requireNonNull(builder.renderingStrategy)) .withTableAliasCalculator(tableAliasCalculator) - .withStatementConfiguration(builder.statementConfiguration) + .withStatementConfiguration(deleteModel.statementConfiguration()) .build(); } @@ -106,7 +105,6 @@ public static Builder withDeleteModel(DeleteModel deleteModel) { public static class Builder { private DeleteModel deleteModel; private RenderingStrategy renderingStrategy; - private StatementConfiguration statementConfiguration; public Builder withDeleteModel(DeleteModel deleteModel) { this.deleteModel = deleteModel; @@ -118,11 +116,6 @@ public Builder withRenderingStrategy(RenderingStrategy renderingStrategy) { return this; } - public Builder withStatementConfiguration(StatementConfiguration statementConfiguration) { - this.statementConfiguration = statementConfiguration; - return this; - } - public DeleteRenderer build() { return new DeleteRenderer(this); } diff --git a/src/main/java/org/mybatis/dynamic/sql/insert/BatchInsertModel.java b/src/main/java/org/mybatis/dynamic/sql/insert/BatchInsertModel.java index 5e48e9035..b591753a2 100644 --- a/src/main/java/org/mybatis/dynamic/sql/insert/BatchInsertModel.java +++ b/src/main/java/org/mybatis/dynamic/sql/insert/BatchInsertModel.java @@ -19,7 +19,7 @@ import org.jetbrains.annotations.NotNull; import org.mybatis.dynamic.sql.insert.render.BatchInsert; -import org.mybatis.dynamic.sql.render.RendererFactory; +import org.mybatis.dynamic.sql.insert.render.BatchInsertRenderer; import org.mybatis.dynamic.sql.render.RenderingStrategy; import org.mybatis.dynamic.sql.util.Validator; @@ -33,8 +33,10 @@ private BatchInsertModel(Builder builder) { @NotNull public BatchInsert render(RenderingStrategy renderingStrategy) { - return RendererFactory.createBatchInsertRenderer(this) - .render(renderingStrategy); + return BatchInsertRenderer.withBatchInsertModel(this) + .withRenderingStrategy(renderingStrategy) + .build() + .render(); } public static Builder withRecords(Collection records) { diff --git a/src/main/java/org/mybatis/dynamic/sql/insert/GeneralInsertModel.java b/src/main/java/org/mybatis/dynamic/sql/insert/GeneralInsertModel.java index f3fb146ee..1fe845090 100644 --- a/src/main/java/org/mybatis/dynamic/sql/insert/GeneralInsertModel.java +++ b/src/main/java/org/mybatis/dynamic/sql/insert/GeneralInsertModel.java @@ -23,8 +23,8 @@ import org.jetbrains.annotations.NotNull; import org.mybatis.dynamic.sql.SqlTable; import org.mybatis.dynamic.sql.configuration.StatementConfiguration; +import org.mybatis.dynamic.sql.insert.render.GeneralInsertRenderer; import org.mybatis.dynamic.sql.insert.render.GeneralInsertStatementProvider; -import org.mybatis.dynamic.sql.render.RendererFactory; import org.mybatis.dynamic.sql.render.RenderingStrategy; import org.mybatis.dynamic.sql.util.AbstractColumnMapping; import org.mybatis.dynamic.sql.util.Validator; @@ -50,10 +50,16 @@ public SqlTable table() { return table; } + public StatementConfiguration statementConfiguration() { + return statementConfiguration; + } + @NotNull public GeneralInsertStatementProvider render(RenderingStrategy renderingStrategy) { - return RendererFactory.createGeneralInsertRenderer(this, statementConfiguration) - .render(renderingStrategy); + return GeneralInsertRenderer.withInsertModel(this) + .withRenderingStrategy(renderingStrategy) + .build() + .render(); } public static class Builder { diff --git a/src/main/java/org/mybatis/dynamic/sql/insert/InsertModel.java b/src/main/java/org/mybatis/dynamic/sql/insert/InsertModel.java index 07fac79ed..7f740051e 100644 --- a/src/main/java/org/mybatis/dynamic/sql/insert/InsertModel.java +++ b/src/main/java/org/mybatis/dynamic/sql/insert/InsertModel.java @@ -22,8 +22,8 @@ import org.jetbrains.annotations.NotNull; import org.mybatis.dynamic.sql.SqlTable; +import org.mybatis.dynamic.sql.insert.render.InsertRenderer; import org.mybatis.dynamic.sql.insert.render.InsertStatementProvider; -import org.mybatis.dynamic.sql.render.RendererFactory; import org.mybatis.dynamic.sql.render.RenderingStrategy; import org.mybatis.dynamic.sql.util.AbstractColumnMapping; import org.mybatis.dynamic.sql.util.Validator; @@ -54,8 +54,10 @@ public SqlTable table() { @NotNull public InsertStatementProvider render(RenderingStrategy renderingStrategy) { - return RendererFactory.createInsertRenderer(this) - .render(renderingStrategy); + return InsertRenderer.withInsertModel(this) + .withRenderingStrategy(renderingStrategy) + .build() + .render(); } public static Builder withRow(T row) { diff --git a/src/main/java/org/mybatis/dynamic/sql/insert/InsertSelectModel.java b/src/main/java/org/mybatis/dynamic/sql/insert/InsertSelectModel.java index 5b22eaeb7..3d9580942 100644 --- a/src/main/java/org/mybatis/dynamic/sql/insert/InsertSelectModel.java +++ b/src/main/java/org/mybatis/dynamic/sql/insert/InsertSelectModel.java @@ -21,8 +21,8 @@ import org.jetbrains.annotations.NotNull; import org.mybatis.dynamic.sql.SqlTable; import org.mybatis.dynamic.sql.configuration.StatementConfiguration; +import org.mybatis.dynamic.sql.insert.render.InsertSelectRenderer; import org.mybatis.dynamic.sql.insert.render.InsertSelectStatementProvider; -import org.mybatis.dynamic.sql.render.RendererFactory; import org.mybatis.dynamic.sql.render.RenderingStrategy; import org.mybatis.dynamic.sql.select.SelectModel; @@ -51,10 +51,16 @@ public Optional columnList() { return Optional.ofNullable(columnList); } + public StatementConfiguration statementConfiguration() { + return statementConfiguration; + } + @NotNull public InsertSelectStatementProvider render(RenderingStrategy renderingStrategy) { - return RendererFactory.createInsertSelectRenderer(this, statementConfiguration) - .render(renderingStrategy); + return InsertSelectRenderer.withInsertSelectModel(this) + .withRenderingStrategy(renderingStrategy) + .build() + .render(); } public static Builder withTable(SqlTable table) { diff --git a/src/main/java/org/mybatis/dynamic/sql/insert/MultiRowInsertModel.java b/src/main/java/org/mybatis/dynamic/sql/insert/MultiRowInsertModel.java index d5d7f478d..406c02b7a 100644 --- a/src/main/java/org/mybatis/dynamic/sql/insert/MultiRowInsertModel.java +++ b/src/main/java/org/mybatis/dynamic/sql/insert/MultiRowInsertModel.java @@ -18,8 +18,8 @@ import java.util.Collection; import org.jetbrains.annotations.NotNull; +import org.mybatis.dynamic.sql.insert.render.MultiRowInsertRenderer; import org.mybatis.dynamic.sql.insert.render.MultiRowInsertStatementProvider; -import org.mybatis.dynamic.sql.render.RendererFactory; import org.mybatis.dynamic.sql.render.RenderingStrategy; import org.mybatis.dynamic.sql.util.Validator; @@ -33,8 +33,10 @@ private MultiRowInsertModel(Builder builder) { @NotNull public MultiRowInsertStatementProvider render(RenderingStrategy renderingStrategy) { - return RendererFactory.createMultiRowInsertRenderer(this) - .render(renderingStrategy); + return MultiRowInsertRenderer.withMultiRowInsertModel(this) + .withRenderingStrategy(renderingStrategy) + .build() + .render(); } public static Builder withRecords(Collection records) { diff --git a/src/main/java/org/mybatis/dynamic/sql/insert/render/DefaultGeneralInsertStatementProvider.java b/src/main/java/org/mybatis/dynamic/sql/insert/render/DefaultGeneralInsertStatementProvider.java index de1c41266..5cd4144d6 100644 --- a/src/main/java/org/mybatis/dynamic/sql/insert/render/DefaultGeneralInsertStatementProvider.java +++ b/src/main/java/org/mybatis/dynamic/sql/insert/render/DefaultGeneralInsertStatementProvider.java @@ -22,11 +22,11 @@ public class DefaultGeneralInsertStatementProvider implements GeneralInsertStatementProvider, InsertSelectStatementProvider { private final String insertStatement; - private final Map parameters = new HashMap<>(); + private final Map parameters; private DefaultGeneralInsertStatementProvider(Builder builder) { insertStatement = Objects.requireNonNull(builder.insertStatement); - parameters.putAll(builder.parameters); + parameters = builder.parameters; } @Override diff --git a/src/main/java/org/mybatis/dynamic/sql/insert/render/GeneralInsertRenderer.java b/src/main/java/org/mybatis/dynamic/sql/insert/render/GeneralInsertRenderer.java index c5378b493..de91037a6 100644 --- a/src/main/java/org/mybatis/dynamic/sql/insert/render/GeneralInsertRenderer.java +++ b/src/main/java/org/mybatis/dynamic/sql/insert/render/GeneralInsertRenderer.java @@ -18,7 +18,6 @@ import java.util.Objects; import java.util.Optional; -import org.mybatis.dynamic.sql.configuration.StatementConfiguration; import org.mybatis.dynamic.sql.insert.GeneralInsertModel; import org.mybatis.dynamic.sql.render.RenderingContext; import org.mybatis.dynamic.sql.render.RenderingStrategy; @@ -32,7 +31,7 @@ public class GeneralInsertRenderer { private GeneralInsertRenderer(Builder builder) { model = Objects.requireNonNull(builder.model); RenderingContext renderingContext = RenderingContext.withRenderingStrategy(builder.renderingStrategy) - .withStatementConfiguration(builder.statementConfiguration) + .withStatementConfiguration(model.statementConfiguration()) .build(); visitor = new GeneralInsertValuePhraseVisitor(renderingContext); } @@ -59,7 +58,6 @@ public static Builder withInsertModel(GeneralInsertModel model) { public static class Builder { private GeneralInsertModel model; private RenderingStrategy renderingStrategy; - private StatementConfiguration statementConfiguration; public Builder withInsertModel(GeneralInsertModel model) { this.model = model; @@ -71,11 +69,6 @@ public Builder withRenderingStrategy(RenderingStrategy renderingStrategy) { return this; } - public Builder withStatementConfiguration(StatementConfiguration statementConfiguration) { - this.statementConfiguration = statementConfiguration; - return this; - } - public GeneralInsertRenderer build() { return new GeneralInsertRenderer(this); } diff --git a/src/main/java/org/mybatis/dynamic/sql/insert/render/InsertSelectRenderer.java b/src/main/java/org/mybatis/dynamic/sql/insert/render/InsertSelectRenderer.java index 16afe6767..cd052f45d 100644 --- a/src/main/java/org/mybatis/dynamic/sql/insert/render/InsertSelectRenderer.java +++ b/src/main/java/org/mybatis/dynamic/sql/insert/render/InsertSelectRenderer.java @@ -15,20 +15,18 @@ */ package org.mybatis.dynamic.sql.insert.render; -import static org.mybatis.dynamic.sql.util.StringUtilities.spaceBefore; +import static org.mybatis.dynamic.sql.util.StringUtilities.spaceAfter; import java.util.Objects; -import java.util.Optional; import java.util.stream.Collectors; import org.mybatis.dynamic.sql.SqlColumn; -import org.mybatis.dynamic.sql.configuration.StatementConfiguration; import org.mybatis.dynamic.sql.insert.InsertColumnListModel; import org.mybatis.dynamic.sql.insert.InsertSelectModel; import org.mybatis.dynamic.sql.render.RenderingContext; import org.mybatis.dynamic.sql.render.RenderingStrategy; -import org.mybatis.dynamic.sql.select.render.SelectStatementProvider; -import org.mybatis.dynamic.sql.util.StringUtilities; +import org.mybatis.dynamic.sql.select.render.SubQueryRenderer; +import org.mybatis.dynamic.sql.util.FragmentAndParameters; public class InsertSelectRenderer { @@ -38,34 +36,34 @@ public class InsertSelectRenderer { private InsertSelectRenderer(Builder builder) { model = Objects.requireNonNull(builder.model); renderingContext = RenderingContext.withRenderingStrategy(builder.renderingStrategy) - .withStatementConfiguration(builder.statementConfiguration) + .withStatementConfiguration(model.statementConfiguration()) .build(); } public InsertSelectStatementProvider render() { - SelectStatementProvider selectStatement = model.selectModel().render(renderingContext); - String statementStart = InsertRenderingUtilities.calculateInsertStatementStart(model.table()); - Optional columnsPhrase = calculateColumnsPhrase(); - String renderedSelectStatement = selectStatement.getSelectStatement(); + String columnsPhrase = calculateColumnsPhrase(); + String prefix = statementStart + spaceAfter(columnsPhrase); - String insertStatement = statementStart - + columnsPhrase.map(StringUtilities::spaceBefore).orElse("") //$NON-NLS-1$ - + spaceBefore(renderedSelectStatement); + FragmentAndParameters fragmentAndParameters = SubQueryRenderer.withSelectModel(model.selectModel()) + .withRenderingContext(renderingContext) + .withPrefix(prefix) + .build() + .render(); - return DefaultGeneralInsertStatementProvider.withInsertStatement(insertStatement) - .withParameters(selectStatement.getParameters()) + return DefaultGeneralInsertStatementProvider.withInsertStatement(fragmentAndParameters.fragment()) + .withParameters(fragmentAndParameters.parameters()) .build(); } - private Optional calculateColumnsPhrase() { - return model.columnList().map(this::calculateColumnsPhrase); + private String calculateColumnsPhrase() { + return model.columnList().map(this::calculateColumnsPhrase).orElse(""); //$NON-NLS-1$ } private String calculateColumnsPhrase(InsertColumnListModel columnList) { return columnList.columns() .map(SqlColumn::name) - .collect(Collectors.joining(", ", "(", ")")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + .collect(Collectors.joining(", ", " (", ")")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } public static Builder withInsertSelectModel(InsertSelectModel model) { @@ -75,7 +73,6 @@ public static Builder withInsertSelectModel(InsertSelectModel model) { public static class Builder { private InsertSelectModel model; private RenderingStrategy renderingStrategy; - private StatementConfiguration statementConfiguration; public Builder withInsertSelectModel(InsertSelectModel model) { this.model = model; @@ -87,11 +84,6 @@ public Builder withRenderingStrategy(RenderingStrategy renderingStrategy) { return this; } - public Builder withStatementConfiguration(StatementConfiguration statementConfiguration) { - this.statementConfiguration = statementConfiguration; - return this; - } - public InsertSelectRenderer build() { return new InsertSelectRenderer(this); } diff --git a/src/main/java/org/mybatis/dynamic/sql/render/Renderer.java b/src/main/java/org/mybatis/dynamic/sql/render/Renderer.java deleted file mode 100644 index acb84a98f..000000000 --- a/src/main/java/org/mybatis/dynamic/sql/render/Renderer.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2016-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.mybatis.dynamic.sql.render; - -@FunctionalInterface -public interface Renderer { - R render(T t); -} diff --git a/src/main/java/org/mybatis/dynamic/sql/render/RendererFactory.java b/src/main/java/org/mybatis/dynamic/sql/render/RendererFactory.java deleted file mode 100644 index c47ca1f78..000000000 --- a/src/main/java/org/mybatis/dynamic/sql/render/RendererFactory.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2016-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.mybatis.dynamic.sql.render; - -import org.mybatis.dynamic.sql.configuration.StatementConfiguration; -import org.mybatis.dynamic.sql.delete.DeleteModel; -import org.mybatis.dynamic.sql.delete.render.DeleteRenderer; -import org.mybatis.dynamic.sql.delete.render.DeleteStatementProvider; -import org.mybatis.dynamic.sql.insert.BatchInsertModel; -import org.mybatis.dynamic.sql.insert.GeneralInsertModel; -import org.mybatis.dynamic.sql.insert.InsertModel; -import org.mybatis.dynamic.sql.insert.InsertSelectModel; -import org.mybatis.dynamic.sql.insert.MultiRowInsertModel; -import org.mybatis.dynamic.sql.insert.render.BatchInsert; -import org.mybatis.dynamic.sql.insert.render.BatchInsertRenderer; -import org.mybatis.dynamic.sql.insert.render.GeneralInsertRenderer; -import org.mybatis.dynamic.sql.insert.render.GeneralInsertStatementProvider; -import org.mybatis.dynamic.sql.insert.render.InsertRenderer; -import org.mybatis.dynamic.sql.insert.render.InsertSelectRenderer; -import org.mybatis.dynamic.sql.insert.render.InsertSelectStatementProvider; -import org.mybatis.dynamic.sql.insert.render.InsertStatementProvider; -import org.mybatis.dynamic.sql.insert.render.MultiRowInsertRenderer; -import org.mybatis.dynamic.sql.insert.render.MultiRowInsertStatementProvider; -import org.mybatis.dynamic.sql.select.MultiSelectModel; -import org.mybatis.dynamic.sql.select.SelectModel; -import org.mybatis.dynamic.sql.select.render.MultiSelectRenderer; -import org.mybatis.dynamic.sql.select.render.SelectRenderer; -import org.mybatis.dynamic.sql.select.render.SelectStatementProvider; -import org.mybatis.dynamic.sql.update.UpdateModel; -import org.mybatis.dynamic.sql.update.render.UpdateRenderer; -import org.mybatis.dynamic.sql.update.render.UpdateStatementProvider; - -public interface RendererFactory { - static Renderer createDeleteRenderer(DeleteModel deleteModel, - StatementConfiguration statementConfiguration) { - return renderingStrategy -> DeleteRenderer.withDeleteModel(deleteModel) - .withStatementConfiguration(statementConfiguration) - .withRenderingStrategy(renderingStrategy) - .build() - .render(); - } - - static Renderer> createBatchInsertRenderer( - BatchInsertModel batchInsertModel) { - return renderingStrategy -> BatchInsertRenderer.withBatchInsertModel(batchInsertModel) - .withRenderingStrategy(renderingStrategy) - .build() - .render(); - } - - static Renderer createGeneralInsertRenderer( - GeneralInsertModel generalInsertModel, StatementConfiguration statementConfiguration) { - return renderingStrategy -> GeneralInsertRenderer.withInsertModel(generalInsertModel) - .withStatementConfiguration(statementConfiguration) - .withRenderingStrategy(renderingStrategy) - .build() - .render(); - } - - static Renderer> createInsertRenderer( - InsertModel insertModel) { - return renderingStrategy -> InsertRenderer.withInsertModel(insertModel) - .withRenderingStrategy(renderingStrategy) - .build() - .render(); - } - - static Renderer createInsertSelectRenderer( - InsertSelectModel insertSelectModel, StatementConfiguration statementConfiguration) { - return renderingStrategy -> InsertSelectRenderer.withInsertSelectModel(insertSelectModel) - .withStatementConfiguration(statementConfiguration) - .withRenderingStrategy(renderingStrategy) - .build() - .render(); - } - - static Renderer> createMultiRowInsertRenderer( - MultiRowInsertModel multiRowInsertModel) { - return renderingStrategy -> MultiRowInsertRenderer.withMultiRowInsertModel(multiRowInsertModel) - .withRenderingStrategy(renderingStrategy) - .build() - .render(); - } - - static Renderer createMultiSelectRenderer( - MultiSelectModel multiSelectModel, StatementConfiguration statementConfiguration) { - return renderingStrategy -> new MultiSelectRenderer.Builder() - .withMultiSelectModel(multiSelectModel) - .withStatementConfiguration(statementConfiguration) - .withRenderingStrategy(renderingStrategy) - .build() - .render(); - } - - static Renderer createSelectRenderer( - SelectModel selectModel) { - return renderingContext -> SelectRenderer.withSelectModel(selectModel) - .withRenderingContext(renderingContext) - .build() - .render(); - } - - static Renderer createUpdateRenderer( - UpdateModel updateModel, StatementConfiguration statementConfiguration) { - return renderingStrategy -> UpdateRenderer.withUpdateModel(updateModel) - .withStatementConfiguration(statementConfiguration) - .withRenderingStrategy(renderingStrategy) - .build() - .render(); - } -} diff --git a/src/main/java/org/mybatis/dynamic/sql/select/AbstractSelectModel.java b/src/main/java/org/mybatis/dynamic/sql/select/AbstractSelectModel.java index 49c20789f..8fc3fb898 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/AbstractSelectModel.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/AbstractSelectModel.java @@ -40,6 +40,10 @@ public Optional pagingModel() { return Optional.ofNullable(pagingModel); } + public StatementConfiguration statementConfiguration() { + return statementConfiguration; + } + public abstract static class AbstractBuilder> { private OrderByModel orderByModel; private PagingModel pagingModel; diff --git a/src/main/java/org/mybatis/dynamic/sql/select/MultiSelectModel.java b/src/main/java/org/mybatis/dynamic/sql/select/MultiSelectModel.java index 607378c20..60539c660 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/MultiSelectModel.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/MultiSelectModel.java @@ -21,8 +21,8 @@ import java.util.stream.Stream; import org.jetbrains.annotations.NotNull; -import org.mybatis.dynamic.sql.render.RendererFactory; import org.mybatis.dynamic.sql.render.RenderingStrategy; +import org.mybatis.dynamic.sql.select.render.MultiSelectRenderer; import org.mybatis.dynamic.sql.select.render.SelectStatementProvider; import org.mybatis.dynamic.sql.util.Validator; @@ -47,8 +47,10 @@ public Stream unionQueries() { @NotNull public SelectStatementProvider render(RenderingStrategy renderingStrategy) { - return RendererFactory.createMultiSelectRenderer(this, statementConfiguration) - .render(renderingStrategy); + return MultiSelectRenderer.withMultiSelectModel(this) + .withRenderingStrategy(renderingStrategy) + .build() + .render(); } public static class Builder extends AbstractBuilder { diff --git a/src/main/java/org/mybatis/dynamic/sql/select/SelectModel.java b/src/main/java/org/mybatis/dynamic/sql/select/SelectModel.java index 85196be7b..da01d09b5 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/SelectModel.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/SelectModel.java @@ -21,9 +21,8 @@ import java.util.stream.Stream; import org.jetbrains.annotations.NotNull; -import org.mybatis.dynamic.sql.render.RendererFactory; -import org.mybatis.dynamic.sql.render.RenderingContext; import org.mybatis.dynamic.sql.render.RenderingStrategy; +import org.mybatis.dynamic.sql.select.render.SelectRenderer; import org.mybatis.dynamic.sql.select.render.SelectStatementProvider; import org.mybatis.dynamic.sql.util.Validator; @@ -42,21 +41,10 @@ public Stream queryExpressions() { @NotNull public SelectStatementProvider render(RenderingStrategy renderingStrategy) { - RenderingContext renderingContext = RenderingContext.withRenderingStrategy(renderingStrategy) - .withStatementConfiguration(statementConfiguration) - .build(); - return render(renderingContext); - } - - /** - * This version is for rendering sub-queries, union queries, etc. - * - * @param renderingContext the rendering context - * @return a rendered select statement and parameters - */ - @NotNull - public SelectStatementProvider render(RenderingContext renderingContext) { - return RendererFactory.createSelectRenderer(this).render(renderingContext); + return SelectRenderer.withSelectModel(this) + .withRenderingStrategy(renderingStrategy) + .build() + .render(); } public static Builder withQueryExpressions(List queryExpressions) { diff --git a/src/main/java/org/mybatis/dynamic/sql/select/render/MultiSelectRenderer.java b/src/main/java/org/mybatis/dynamic/sql/select/render/MultiSelectRenderer.java index c063e7866..634896ad2 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/render/MultiSelectRenderer.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/render/MultiSelectRenderer.java @@ -21,7 +21,6 @@ import org.mybatis.dynamic.sql.common.OrderByModel; import org.mybatis.dynamic.sql.common.OrderByRenderer; -import org.mybatis.dynamic.sql.configuration.StatementConfiguration; import org.mybatis.dynamic.sql.render.RenderingContext; import org.mybatis.dynamic.sql.render.RenderingStrategy; import org.mybatis.dynamic.sql.select.MultiSelectModel; @@ -36,11 +35,11 @@ public class MultiSelectRenderer { private final RenderingContext renderingContext; private MultiSelectRenderer(Builder builder) { + multiSelectModel = Objects.requireNonNull(builder.multiSelectModel); renderingContext = RenderingContext .withRenderingStrategy(builder.renderingStrategy) - .withStatementConfiguration(builder.statementConfiguration) + .withStatementConfiguration(multiSelectModel.statementConfiguration()) .build(); - multiSelectModel = Objects.requireNonNull(builder.multiSelectModel); } public SelectStatementProvider render() { @@ -65,21 +64,21 @@ private SelectStatementProvider toSelectStatementProvider(FragmentCollector frag } private FragmentAndParameters renderSelect(SelectModel selectModel) { - SelectStatementProvider selectStatement = selectModel.render(renderingContext); - - return FragmentAndParameters - .withFragment("(" + selectStatement.getSelectStatement() + ")") //$NON-NLS-1$ //$NON-NLS-2$ - .withParameters(selectStatement.getParameters()) - .build(); + return SubQueryRenderer.withSelectModel(selectModel) + .withRenderingContext(renderingContext) + .withPrefix("(") //$NON-NLS-1$ + .withSuffix(")") //$NON-NLS-1$ + .build() + .render(); } private FragmentAndParameters renderSelect(UnionQuery unionQuery) { - SelectStatementProvider selectStatement = unionQuery.selectModel().render(renderingContext); - - return FragmentAndParameters.withFragment( - unionQuery.connector() + " (" + selectStatement.getSelectStatement() + ")") //$NON-NLS-1$ //$NON-NLS-2$ - .withParameters(selectStatement.getParameters()) - .build(); + return SubQueryRenderer.withSelectModel(unionQuery.selectModel()) + .withRenderingContext(renderingContext) + .withPrefix(unionQuery.connector() + " (") //$NON-NLS-1$ + .withSuffix(")") //$NON-NLS-1$ + .build() + .render(); } private Optional renderOrderBy() { @@ -102,10 +101,13 @@ private FragmentAndParameters renderPagingModel(PagingModel pagingModel) { .render(); } + public static Builder withMultiSelectModel(MultiSelectModel multiSelectModel) { + return new Builder().withMultiSelectModel(multiSelectModel); + } + public static class Builder { private RenderingStrategy renderingStrategy; private MultiSelectModel multiSelectModel; - private StatementConfiguration statementConfiguration; public Builder withRenderingStrategy(RenderingStrategy renderingStrategy) { this.renderingStrategy = renderingStrategy; @@ -117,11 +119,6 @@ public Builder withMultiSelectModel(MultiSelectModel multiSelectModel) { return this; } - public Builder withStatementConfiguration(StatementConfiguration statementConfiguration) { - this.statementConfiguration = statementConfiguration; - return this; - } - public MultiSelectRenderer build() { return new MultiSelectRenderer(this); } diff --git a/src/main/java/org/mybatis/dynamic/sql/select/render/QueryExpressionRenderer.java b/src/main/java/org/mybatis/dynamic/sql/select/render/QueryExpressionRenderer.java index 0f3ddcb01..618ea2f9c 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/render/QueryExpressionRenderer.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/render/QueryExpressionRenderer.java @@ -139,12 +139,8 @@ private FragmentAndParameters calculateColumnList() { private FragmentAndParameters renderColumnAndAlias(BasicColumn selectListItem) { FragmentAndParameters renderedColumn = selectListItem.render(renderingContext); - String nameAndTableAlias = selectListItem.alias().map(a -> renderedColumn.fragment() + " as " + a) //$NON-NLS-1$ - .orElse(renderedColumn.fragment()); - - return FragmentAndParameters.withFragment(nameAndTableAlias) - .withParameters(renderedColumn.parameters()) - .build(); + return selectListItem.alias().map(a -> renderedColumn.mapFragment(f -> f + " as " + a)) //$NON-NLS-1$ + .orElse(renderedColumn); } private FragmentAndParameters renderTableExpression(TableExpression table) { diff --git a/src/main/java/org/mybatis/dynamic/sql/select/render/SelectRenderer.java b/src/main/java/org/mybatis/dynamic/sql/select/render/SelectRenderer.java index 128ab3e8e..6284b0b49 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/render/SelectRenderer.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/render/SelectRenderer.java @@ -16,71 +16,34 @@ package org.mybatis.dynamic.sql.select.render; import java.util.Objects; -import java.util.Optional; -import java.util.stream.Collectors; -import org.mybatis.dynamic.sql.common.OrderByModel; -import org.mybatis.dynamic.sql.common.OrderByRenderer; import org.mybatis.dynamic.sql.render.RenderingContext; -import org.mybatis.dynamic.sql.select.PagingModel; -import org.mybatis.dynamic.sql.select.QueryExpressionModel; +import org.mybatis.dynamic.sql.render.RenderingStrategy; import org.mybatis.dynamic.sql.select.SelectModel; import org.mybatis.dynamic.sql.util.FragmentAndParameters; -import org.mybatis.dynamic.sql.util.FragmentCollector; public class SelectRenderer { private final SelectModel selectModel; - private final RenderingContext renderingContext; + private final RenderingStrategy renderingStrategy; private SelectRenderer(Builder builder) { selectModel = Objects.requireNonNull(builder.selectModel); - renderingContext = Objects.requireNonNull(builder.renderingContext); + renderingStrategy = Objects.requireNonNull(builder.renderingStrategy); } public SelectStatementProvider render() { - FragmentCollector fragmentCollector = selectModel - .queryExpressions() - .map(this::renderQueryExpression) - .collect(FragmentCollector.collect()); - - renderOrderBy().ifPresent(fragmentCollector::add); - renderPagingModel().ifPresent(fragmentCollector::add); - - return toSelectStatementProvider(fragmentCollector); - } - - private SelectStatementProvider toSelectStatementProvider(FragmentCollector fragmentCollector) { - return DefaultSelectStatementProvider - .withSelectStatement(fragmentCollector.collectFragments(Collectors.joining(" "))) //$NON-NLS-1$ - .withParameters(fragmentCollector.parameters()) + RenderingContext renderingContext = RenderingContext.withRenderingStrategy(renderingStrategy) + .withStatementConfiguration(selectModel.statementConfiguration()) .build(); - } - private FragmentAndParameters renderQueryExpression(QueryExpressionModel queryExpressionModel) { - return QueryExpressionRenderer.withQueryExpression(queryExpressionModel) + FragmentAndParameters fragmentAndParameters = SubQueryRenderer.withSelectModel(selectModel) .withRenderingContext(renderingContext) .build() .render(); - } - - private Optional renderOrderBy() { - return selectModel.orderByModel().map(this::renderOrderBy); - } - private FragmentAndParameters renderOrderBy(OrderByModel orderByModel) { - return new OrderByRenderer(renderingContext).render(orderByModel); - } - - private Optional renderPagingModel() { - return selectModel.pagingModel().map(this::renderPagingModel); - } - - private FragmentAndParameters renderPagingModel(PagingModel pagingModel) { - return new PagingModelRenderer.Builder() - .withPagingModel(pagingModel) - .withRenderingContext(renderingContext) - .build() - .render(); + return DefaultSelectStatementProvider.withSelectStatement(fragmentAndParameters.fragment()) + .withParameters(fragmentAndParameters.parameters()) + .build(); } public static Builder withSelectModel(SelectModel selectModel) { @@ -89,10 +52,10 @@ public static Builder withSelectModel(SelectModel selectModel) { public static class Builder { private SelectModel selectModel; - private RenderingContext renderingContext; + private RenderingStrategy renderingStrategy; - public Builder withRenderingContext(RenderingContext renderingContext) { - this.renderingContext = renderingContext; + public Builder withRenderingStrategy(RenderingStrategy renderingStrategy) { + this.renderingStrategy = renderingStrategy; return this; } diff --git a/src/main/java/org/mybatis/dynamic/sql/select/render/SubQueryRenderer.java b/src/main/java/org/mybatis/dynamic/sql/select/render/SubQueryRenderer.java new file mode 100644 index 000000000..b1d6c28ce --- /dev/null +++ b/src/main/java/org/mybatis/dynamic/sql/select/render/SubQueryRenderer.java @@ -0,0 +1,117 @@ +/* + * Copyright 2016-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.dynamic.sql.select.render; + +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.mybatis.dynamic.sql.common.OrderByModel; +import org.mybatis.dynamic.sql.common.OrderByRenderer; +import org.mybatis.dynamic.sql.render.RenderingContext; +import org.mybatis.dynamic.sql.select.PagingModel; +import org.mybatis.dynamic.sql.select.QueryExpressionModel; +import org.mybatis.dynamic.sql.select.SelectModel; +import org.mybatis.dynamic.sql.util.FragmentAndParameters; +import org.mybatis.dynamic.sql.util.FragmentCollector; + +public class SubQueryRenderer { + private final SelectModel selectModel; + private final RenderingContext renderingContext; + private final String prefix; + private final String suffix; + + private SubQueryRenderer(Builder builder) { + selectModel = Objects.requireNonNull(builder.selectModel); + renderingContext = Objects.requireNonNull(builder.renderingContext); + prefix = builder.prefix == null ? "" : builder.prefix; //$NON-NLS-1$ + suffix = builder.suffix == null ? "" : builder.suffix; //$NON-NLS-1$ + } + + public FragmentAndParameters render() { + FragmentCollector fragmentCollector = selectModel + .queryExpressions() + .map(this::renderQueryExpression) + .collect(FragmentCollector.collect()); + + renderOrderBy().ifPresent(fragmentCollector::add); + renderPagingModel().ifPresent(fragmentCollector::add); + + return fragmentCollector.toFragmentAndParameters(Collectors.joining(" ", prefix, suffix)); //$NON-NLS-1$ + } + + private FragmentAndParameters renderQueryExpression(QueryExpressionModel queryExpressionModel) { + return QueryExpressionRenderer.withQueryExpression(queryExpressionModel) + .withRenderingContext(renderingContext) + .build() + .render(); + } + + private Optional renderOrderBy() { + return selectModel.orderByModel().map(this::renderOrderBy); + } + + private FragmentAndParameters renderOrderBy(OrderByModel orderByModel) { + return new OrderByRenderer(renderingContext).render(orderByModel); + } + + private Optional renderPagingModel() { + return selectModel.pagingModel().map(this::renderPagingModel); + } + + private FragmentAndParameters renderPagingModel(PagingModel pagingModel) { + return new PagingModelRenderer.Builder() + .withPagingModel(pagingModel) + .withRenderingContext(renderingContext) + .build() + .render(); + } + + public static Builder withSelectModel(SelectModel selectModel) { + return new Builder().withSelectModel(selectModel); + } + + public static class Builder { + private SelectModel selectModel; + private RenderingContext renderingContext; + private String prefix; + private String suffix; + + public Builder withRenderingContext(RenderingContext renderingContext) { + this.renderingContext = renderingContext; + return this; + } + + public Builder withSelectModel(SelectModel selectModel) { + this.selectModel = selectModel; + return this; + } + + public Builder withPrefix(String prefix) { + this.prefix = prefix; + return this; + } + + public Builder withSuffix(String suffix) { + this.suffix = suffix; + return this; + } + + public SubQueryRenderer build() { + return new SubQueryRenderer(this); + } + } +} diff --git a/src/main/java/org/mybatis/dynamic/sql/select/render/TableExpressionRenderer.java b/src/main/java/org/mybatis/dynamic/sql/select/render/TableExpressionRenderer.java index ccb9b1d84..24dfb190f 100644 --- a/src/main/java/org/mybatis/dynamic/sql/select/render/TableExpressionRenderer.java +++ b/src/main/java/org/mybatis/dynamic/sql/select/render/TableExpressionRenderer.java @@ -15,8 +15,6 @@ */ package org.mybatis.dynamic.sql.select.render; -import static org.mybatis.dynamic.sql.util.StringUtilities.spaceBefore; - import java.util.Objects; import org.mybatis.dynamic.sql.SqlTable; @@ -39,21 +37,15 @@ public FragmentAndParameters visit(SqlTable table) { @Override public FragmentAndParameters visit(SubQuery subQuery) { - SelectStatementProvider selectStatement = subQuery.selectModel().render(renderingContext); - - String fragment = "(" + selectStatement.getSelectStatement() + ")"; //$NON-NLS-1$ //$NON-NLS-2$ - - fragment = applyAlias(fragment, subQuery); - - return FragmentAndParameters.withFragment(fragment) - .withParameters(selectStatement.getParameters()) - .build(); - } - - private String applyAlias(String fragment, SubQuery subQuery) { - return subQuery.alias() - .map(a -> fragment + spaceBefore(a)) - .orElse(fragment); + String suffix = subQuery.alias().map(a -> ") " + a) //$NON-NLS-1$ + .orElse(")"); //$NON-NLS-1$ + + return SubQueryRenderer.withSelectModel(subQuery.selectModel()) + .withRenderingContext(renderingContext) + .withPrefix("(")//$NON-NLS-1$ + .withSuffix(suffix) + .build() + .render(); } public static class Builder { diff --git a/src/main/java/org/mybatis/dynamic/sql/update/UpdateModel.java b/src/main/java/org/mybatis/dynamic/sql/update/UpdateModel.java index 672b08c44..2c828da91 100644 --- a/src/main/java/org/mybatis/dynamic/sql/update/UpdateModel.java +++ b/src/main/java/org/mybatis/dynamic/sql/update/UpdateModel.java @@ -26,8 +26,8 @@ import org.mybatis.dynamic.sql.common.CommonBuilder; import org.mybatis.dynamic.sql.common.OrderByModel; import org.mybatis.dynamic.sql.configuration.StatementConfiguration; -import org.mybatis.dynamic.sql.render.RendererFactory; import org.mybatis.dynamic.sql.render.RenderingStrategy; +import org.mybatis.dynamic.sql.update.render.UpdateRenderer; import org.mybatis.dynamic.sql.update.render.UpdateStatementProvider; import org.mybatis.dynamic.sql.util.AbstractColumnMapping; import org.mybatis.dynamic.sql.util.Validator; @@ -77,10 +77,16 @@ public Optional orderByModel() { return Optional.ofNullable(orderByModel); } + public StatementConfiguration statementConfiguration() { + return statementConfiguration; + } + @NotNull public UpdateStatementProvider render(RenderingStrategy renderingStrategy) { - return RendererFactory.createUpdateRenderer(this, statementConfiguration) - .render(renderingStrategy); + return UpdateRenderer.withUpdateModel(this) + .withRenderingStrategy(renderingStrategy) + .build() + .render(); } public static Builder withTable(SqlTable table) { diff --git a/src/main/java/org/mybatis/dynamic/sql/update/render/DefaultUpdateStatementProvider.java b/src/main/java/org/mybatis/dynamic/sql/update/render/DefaultUpdateStatementProvider.java index a103bd604..c2f14fbd6 100644 --- a/src/main/java/org/mybatis/dynamic/sql/update/render/DefaultUpdateStatementProvider.java +++ b/src/main/java/org/mybatis/dynamic/sql/update/render/DefaultUpdateStatementProvider.java @@ -21,11 +21,11 @@ public class DefaultUpdateStatementProvider implements UpdateStatementProvider { private final String updateStatement; - private final Map parameters = new HashMap<>(); + private final Map parameters; private DefaultUpdateStatementProvider(Builder builder) { updateStatement = Objects.requireNonNull(builder.updateStatement); - parameters.putAll(builder.parameters); + parameters = builder.parameters; } @Override diff --git a/src/main/java/org/mybatis/dynamic/sql/update/render/SetPhraseVisitor.java b/src/main/java/org/mybatis/dynamic/sql/update/render/SetPhraseVisitor.java index 07d955c80..7bbe575fc 100644 --- a/src/main/java/org/mybatis/dynamic/sql/update/render/SetPhraseVisitor.java +++ b/src/main/java/org/mybatis/dynamic/sql/update/render/SetPhraseVisitor.java @@ -20,7 +20,7 @@ import org.mybatis.dynamic.sql.render.RenderedParameterInfo; import org.mybatis.dynamic.sql.render.RenderingContext; -import org.mybatis.dynamic.sql.select.render.SelectStatementProvider; +import org.mybatis.dynamic.sql.select.render.SubQueryRenderer; import org.mybatis.dynamic.sql.util.AbstractColumnMapping; import org.mybatis.dynamic.sql.util.ColumnToColumnMapping; import org.mybatis.dynamic.sql.util.ConstantMapping; @@ -84,28 +84,23 @@ public Optional visit(ValueWhenPresentMapping mapp @Override public Optional visit(SelectMapping mapping) { - SelectStatementProvider selectStatement = mapping.selectModel().render(renderingContext); - String fragment = renderingContext.aliasedColumnName(mapping.column()) - + " = (" //$NON-NLS-1$ - + selectStatement.getSelectStatement() - + ")"; //$NON-NLS-1$ + String prefix = renderingContext.aliasedColumnName(mapping.column()) + " = ("; //$NON-NLS-1$ - return FragmentAndParameters.withFragment(fragment) - .withParameters(selectStatement.getParameters()) - .buildOptional(); + FragmentAndParameters fragmentAndParameters = SubQueryRenderer.withSelectModel(mapping.selectModel()) + .withRenderingContext(renderingContext) + .withPrefix(prefix) + .withSuffix(")") //$NON-NLS-1$ + .build() + .render(); + + return Optional.of(fragmentAndParameters); } @Override public Optional visit(ColumnToColumnMapping mapping) { - FragmentAndParameters renderedColumn = mapping.rightColumn().render(renderingContext); - - String setPhrase = renderingContext.aliasedColumnName(mapping.column()) - + " = " //$NON-NLS-1$ - + renderedColumn.fragment(); - - return FragmentAndParameters.withFragment(setPhrase) - .withParameters(renderedColumn.parameters()) - .buildOptional(); + FragmentAndParameters fragmentAndParameters = mapping.rightColumn().render(renderingContext) + .mapFragment(f -> renderingContext.aliasedColumnName(mapping.column()) + " = " + f); //$NON-NLS-1$ + return Optional.of(fragmentAndParameters); } private Optional buildValueFragment(AbstractColumnMapping mapping, T value) { diff --git a/src/main/java/org/mybatis/dynamic/sql/update/render/UpdateRenderer.java b/src/main/java/org/mybatis/dynamic/sql/update/render/UpdateRenderer.java index 352c1de7a..3af6aa6d2 100644 --- a/src/main/java/org/mybatis/dynamic/sql/update/render/UpdateRenderer.java +++ b/src/main/java/org/mybatis/dynamic/sql/update/render/UpdateRenderer.java @@ -22,7 +22,6 @@ import org.mybatis.dynamic.sql.common.OrderByModel; import org.mybatis.dynamic.sql.common.OrderByRenderer; -import org.mybatis.dynamic.sql.configuration.StatementConfiguration; import org.mybatis.dynamic.sql.render.ExplicitTableAliasCalculator; import org.mybatis.dynamic.sql.render.RenderedParameterInfo; import org.mybatis.dynamic.sql.render.RenderingContext; @@ -47,7 +46,7 @@ private UpdateRenderer(Builder builder) { renderingContext = RenderingContext .withRenderingStrategy(Objects.requireNonNull(builder.renderingStrategy)) .withTableAliasCalculator(tableAliasCalculator) - .withStatementConfiguration(builder.statementConfiguration) + .withStatementConfiguration(updateModel.statementConfiguration()) .build(); visitor = new SetPhraseVisitor(renderingContext); } @@ -131,7 +130,6 @@ public static Builder withUpdateModel(UpdateModel updateModel) { public static class Builder { private UpdateModel updateModel; private RenderingStrategy renderingStrategy; - private StatementConfiguration statementConfiguration; public Builder withUpdateModel(UpdateModel updateModel) { this.updateModel = updateModel; @@ -143,11 +141,6 @@ public Builder withRenderingStrategy(RenderingStrategy renderingStrategy) { return this; } - public Builder withStatementConfiguration(StatementConfiguration statementConfiguration) { - this.statementConfiguration = statementConfiguration; - return this; - } - public UpdateRenderer build() { return new UpdateRenderer(this); } diff --git a/src/main/java/org/mybatis/dynamic/sql/util/FragmentAndParameters.java b/src/main/java/org/mybatis/dynamic/sql/util/FragmentAndParameters.java index 4c240120c..8f2b58aae 100644 --- a/src/main/java/org/mybatis/dynamic/sql/util/FragmentAndParameters.java +++ b/src/main/java/org/mybatis/dynamic/sql/util/FragmentAndParameters.java @@ -15,6 +15,7 @@ */ package org.mybatis.dynamic.sql.util; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Objects; @@ -28,7 +29,7 @@ public class FragmentAndParameters { private FragmentAndParameters(Builder builder) { fragment = Objects.requireNonNull(builder.fragment); - parameters = Objects.requireNonNull(builder.parameters); + parameters = Collections.unmodifiableMap(builder.parameters); } public String fragment() { 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 8db761223..5c99d68ff 100644 --- a/src/main/java/org/mybatis/dynamic/sql/where/WhereModel.java +++ b/src/main/java/org/mybatis/dynamic/sql/where/WhereModel.java @@ -24,6 +24,7 @@ import org.mybatis.dynamic.sql.render.RenderingStrategy; import org.mybatis.dynamic.sql.render.TableAliasCalculator; import org.mybatis.dynamic.sql.util.FragmentAndParameters; +import org.mybatis.dynamic.sql.where.render.DefaultWhereClauseProvider; import org.mybatis.dynamic.sql.where.render.WhereClauseProvider; import org.mybatis.dynamic.sql.where.render.WhereRenderer; @@ -92,7 +93,7 @@ private Optional render(RenderingContext renderingContext) } private WhereClauseProvider toWhereClauseProvider(FragmentAndParameters fragmentAndParameters) { - return WhereClauseProvider.withWhereClause(fragmentAndParameters.fragment()) + return DefaultWhereClauseProvider.withWhereClause(fragmentAndParameters.fragment()) .withParameters(fragmentAndParameters.parameters()) .build(); } diff --git a/src/main/java/org/mybatis/dynamic/sql/where/render/CriterionRenderer.java b/src/main/java/org/mybatis/dynamic/sql/where/render/CriterionRenderer.java index 0e4325179..7e29a10d3 100644 --- a/src/main/java/org/mybatis/dynamic/sql/where/render/CriterionRenderer.java +++ b/src/main/java/org/mybatis/dynamic/sql/where/render/CriterionRenderer.java @@ -30,7 +30,7 @@ import org.mybatis.dynamic.sql.SqlCriterion; import org.mybatis.dynamic.sql.SqlCriterionVisitor; import org.mybatis.dynamic.sql.render.RenderingContext; -import org.mybatis.dynamic.sql.select.render.SelectStatementProvider; +import org.mybatis.dynamic.sql.select.render.SubQueryRenderer; import org.mybatis.dynamic.sql.util.FragmentAndParameters; import org.mybatis.dynamic.sql.util.FragmentCollector; @@ -119,18 +119,12 @@ private Optional renderColumnAndCondition(ColumnAndCo private FragmentAndParameters renderExists(ExistsCriterion criterion) { ExistsPredicate existsPredicate = criterion.existsPredicate(); - - SelectStatementProvider selectStatement = existsPredicate.selectModelBuilder().build().render(renderingContext); - - String fragment = existsPredicate.operator() - + " (" //$NON-NLS-1$ - + selectStatement.getSelectStatement() - + ")"; //$NON-NLS-1$ - - return FragmentAndParameters - .withFragment(fragment) - .withParameters(selectStatement.getParameters()) - .build(); + return SubQueryRenderer.withSelectModel(existsPredicate.selectModelBuilder().build()) + .withRenderingContext(renderingContext) + .withPrefix(existsPredicate.operator() + " (") //$NON-NLS-1$ + .withSuffix(")") //$NON-NLS-1$ + .build() + .render(); } private List renderSubCriteria(List subCriteria) { diff --git a/src/main/java/org/mybatis/dynamic/sql/where/render/DefaultConditionVisitor.java b/src/main/java/org/mybatis/dynamic/sql/where/render/DefaultConditionVisitor.java index 9adda9f64..d5cdc0dd2 100644 --- a/src/main/java/org/mybatis/dynamic/sql/where/render/DefaultConditionVisitor.java +++ b/src/main/java/org/mybatis/dynamic/sql/where/render/DefaultConditionVisitor.java @@ -30,7 +30,7 @@ import org.mybatis.dynamic.sql.ConditionVisitor; import org.mybatis.dynamic.sql.render.RenderedParameterInfo; import org.mybatis.dynamic.sql.render.RenderingContext; -import org.mybatis.dynamic.sql.select.render.SelectStatementProvider; +import org.mybatis.dynamic.sql.select.render.SubQueryRenderer; import org.mybatis.dynamic.sql.util.FragmentAndParameters; import org.mybatis.dynamic.sql.util.FragmentCollector; @@ -95,26 +95,18 @@ public FragmentAndParameters visit(AbstractTwoValueCondition condition) { @Override public FragmentAndParameters visit(AbstractSubselectCondition condition) { - SelectStatementProvider selectStatement = condition.selectModel().render(renderingContext); - - String finalFragment = condition.operator() - + " (" //$NON-NLS-1$ - + selectStatement.getSelectStatement() - + ")"; //$NON-NLS-1$ - - return FragmentAndParameters.withFragment(finalFragment) - .withParameters(selectStatement.getParameters()) - .build(); + return SubQueryRenderer.withSelectModel(condition.selectModel()) + .withRenderingContext(renderingContext) + .withPrefix(condition.operator() + " (") //$NON-NLS-1$ + .withSuffix(")") //$NON-NLS-1$ + .build() + .render(); } @Override public FragmentAndParameters visit(AbstractColumnComparisonCondition condition) { - FragmentAndParameters renderedRightColumn = condition.rightColumn().render(renderingContext); - String finalFragment = condition.operator() - + spaceBefore(renderedRightColumn.fragment()); - return FragmentAndParameters.withFragment(finalFragment) - .withParameters(renderedRightColumn.parameters()) - .build(); + return condition.rightColumn().render(renderingContext) + .mapFragment(f -> condition.operator() + spaceBefore(f)); } private Object convertValue(T value) { diff --git a/src/main/java/org/mybatis/dynamic/sql/where/render/DefaultWhereClauseProvider.java b/src/main/java/org/mybatis/dynamic/sql/where/render/DefaultWhereClauseProvider.java new file mode 100644 index 000000000..bf68eb7cf --- /dev/null +++ b/src/main/java/org/mybatis/dynamic/sql/where/render/DefaultWhereClauseProvider.java @@ -0,0 +1,63 @@ +/* + * Copyright 2016-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.dynamic.sql.where.render; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +public class DefaultWhereClauseProvider implements WhereClauseProvider { + private final String whereClause; + private final Map parameters; + + private DefaultWhereClauseProvider(Builder builder) { + whereClause = Objects.requireNonNull(builder.whereClause); + parameters = builder.parameters; + } + + @Override + public Map getParameters() { + return parameters; + } + + @Override + public String getWhereClause() { + return whereClause; + } + + public static Builder withWhereClause(String whereClause) { + return new Builder().withWhereClause(whereClause); + } + + public static class Builder { + private String whereClause; + private final Map parameters = new HashMap<>(); + + public Builder withWhereClause(String whereClause) { + this.whereClause = whereClause; + return this; + } + + public Builder withParameters(Map parameters) { + this.parameters.putAll(parameters); + return this; + } + + public DefaultWhereClauseProvider build() { + return new DefaultWhereClauseProvider(this); + } + } +} diff --git a/src/main/java/org/mybatis/dynamic/sql/where/render/WhereClauseProvider.java b/src/main/java/org/mybatis/dynamic/sql/where/render/WhereClauseProvider.java index 37d051e81..1e8d16be5 100644 --- a/src/main/java/org/mybatis/dynamic/sql/where/render/WhereClauseProvider.java +++ b/src/main/java/org/mybatis/dynamic/sql/where/render/WhereClauseProvider.java @@ -15,48 +15,10 @@ */ package org.mybatis.dynamic.sql.where.render; -import java.util.Collections; -import java.util.HashMap; import java.util.Map; -import java.util.Objects; -public class WhereClauseProvider { - private final String whereClause; - private final Map parameters; +public interface WhereClauseProvider { + Map getParameters(); - private WhereClauseProvider(Builder builder) { - whereClause = Objects.requireNonNull(builder.whereClause); - parameters = Objects.requireNonNull(builder.parameters); - } - - public Map getParameters() { - return Collections.unmodifiableMap(parameters); - } - - public String getWhereClause() { - return whereClause; - } - - public static Builder withWhereClause(String whereClause) { - return new Builder().withWhereClause(whereClause); - } - - public static class Builder { - private String whereClause; - private final Map parameters = new HashMap<>(); - - public Builder withWhereClause(String whereClause) { - this.whereClause = whereClause; - return this; - } - - public Builder withParameters(Map parameters) { - this.parameters.putAll(parameters); - return this; - } - - public WhereClauseProvider build() { - return new WhereClauseProvider(this); - } - } + String getWhereClause(); } diff --git a/src/test/java/config/TestContainersConfiguration.java b/src/test/java/config/TestContainersConfiguration.java index fc6607dbb..1919fc0f9 100644 --- a/src/test/java/config/TestContainersConfiguration.java +++ b/src/test/java/config/TestContainersConfiguration.java @@ -21,6 +21,6 @@ * Utility interface to hold Docker image tags for the test containers we use */ public interface TestContainersConfiguration { - DockerImageName POSTGRES_LATEST = DockerImageName.parse("postgres:17.0"); - DockerImageName MARIADB_LATEST = DockerImageName.parse("mariadb:11.5.2"); + DockerImageName POSTGRES_LATEST = DockerImageName.parse("postgres:17.2"); + DockerImageName MARIADB_LATEST = DockerImageName.parse("mariadb:11.6.2"); } diff --git a/src/test/java/examples/animal/data/Length.java b/src/test/java/examples/animal/data/Length.java index 6fb90e40d..34bb7f3c9 100644 --- a/src/test/java/examples/animal/data/Length.java +++ b/src/test/java/examples/animal/data/Length.java @@ -36,11 +36,8 @@ public Optional jdbcType() { @Override public FragmentAndParameters render(RenderingContext renderingContext) { - FragmentAndParameters renderedColumn = column.render(renderingContext); - - return FragmentAndParameters.withFragment("length(" + renderedColumn.fragment() + ")") //$NON-NLS-1$ //$NON-NLS-2$ - .withParameters(renderedColumn.parameters()) - .build(); + return column.render(renderingContext) + .mapFragment(f -> "length(" + f + ")"); //$NON-NLS-1$ //$NON-NLS-2$ } @Override diff --git a/src/test/java/examples/type_conversion/ToBase64.java b/src/test/java/examples/type_conversion/ToBase64.java index ce5ab5891..42bfe40d1 100644 --- a/src/test/java/examples/type_conversion/ToBase64.java +++ b/src/test/java/examples/type_conversion/ToBase64.java @@ -37,11 +37,8 @@ public Optional jdbcType() { @Override public FragmentAndParameters render(RenderingContext renderingContext) { - FragmentAndParameters renderedColumn = column.render(renderingContext); - - return FragmentAndParameters.withFragment("TO_BASE64(" + renderedColumn.fragment() + ")") //$NON-NLS-1$ //$NON-NLS-2$ - .withParameters(renderedColumn.parameters()) - .build(); + return column.render(renderingContext) + .mapFragment(f -> "TO_BASE64(" + f + ")"); //$NON-NLS-1$ //$NON-NLS-2$ } @Override