View Javadoc
1   /*
2    *    Copyright 2016-2025 the original author or authors.
3    *
4    *    Licensed under the Apache License, Version 2.0 (the "License");
5    *    you may not use this file except in compliance with the License.
6    *    You may obtain a copy of the License at
7    *
8    *       https://www.apache.org/licenses/LICENSE-2.0
9    *
10   *    Unless required by applicable law or agreed to in writing, software
11   *    distributed under the License is distributed on an "AS IS" BASIS,
12   *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *    See the License for the specific language governing permissions and
14   *    limitations under the License.
15   */
16  package org.mybatis.dynamic.sql.insert.render;
17  
18  import static org.mybatis.dynamic.sql.util.StringUtilities.spaceAfter;
19  
20  import java.util.Objects;
21  import java.util.stream.Collectors;
22  
23  import org.jspecify.annotations.Nullable;
24  import org.mybatis.dynamic.sql.SqlColumn;
25  import org.mybatis.dynamic.sql.insert.InsertColumnListModel;
26  import org.mybatis.dynamic.sql.insert.InsertSelectModel;
27  import org.mybatis.dynamic.sql.render.RenderingContext;
28  import org.mybatis.dynamic.sql.render.RenderingStrategy;
29  import org.mybatis.dynamic.sql.select.render.SubQueryRenderer;
30  import org.mybatis.dynamic.sql.util.FragmentAndParameters;
31  
32  public class InsertSelectRenderer {
33  
34      private final InsertSelectModel model;
35      private final RenderingContext renderingContext;
36  
37      private InsertSelectRenderer(Builder builder) {
38          model = Objects.requireNonNull(builder.model);
39          renderingContext = RenderingContext.withRenderingStrategy(Objects.requireNonNull(builder.renderingStrategy))
40                  .withStatementConfiguration(model.statementConfiguration())
41                  .build();
42      }
43  
44      public InsertSelectStatementProvider render() {
45          String statementStart = InsertRenderingUtilities.calculateInsertStatementStart(model.table());
46          String columnsPhrase = calculateColumnsPhrase();
47          String prefix = statementStart + spaceAfter(columnsPhrase);
48  
49          FragmentAndParameters fragmentAndParameters = SubQueryRenderer.withSelectModel(model.selectModel())
50                  .withRenderingContext(renderingContext)
51                  .withPrefix(prefix)
52                  .build()
53                  .render();
54  
55          return DefaultGeneralInsertStatementProvider.withInsertStatement(fragmentAndParameters.fragment())
56                  .withParameters(fragmentAndParameters.parameters())
57                  .build();
58      }
59  
60      private String calculateColumnsPhrase() {
61          return model.columnList().map(this::calculateColumnsPhrase).orElse(""); //$NON-NLS-1$
62      }
63  
64      private String calculateColumnsPhrase(InsertColumnListModel columnList) {
65          return columnList.columns()
66                  .map(SqlColumn::name)
67                  .collect(Collectors.joining(", ", " (", ")")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
68      }
69  
70      public static Builder withInsertSelectModel(InsertSelectModel model) {
71          return new Builder().withInsertSelectModel(model);
72      }
73  
74      public static class Builder {
75          private @Nullable InsertSelectModel model;
76          private @Nullable RenderingStrategy renderingStrategy;
77  
78          public Builder withInsertSelectModel(InsertSelectModel model) {
79              this.model = model;
80              return this;
81          }
82  
83          public Builder withRenderingStrategy(RenderingStrategy renderingStrategy) {
84              this.renderingStrategy = renderingStrategy;
85              return this;
86          }
87  
88          public InsertSelectRenderer build() {
89              return new InsertSelectRenderer(this);
90          }
91      }
92  }