1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.mybatis.dynamic.sql.delete.render;
17
18 import java.util.Objects;
19 import java.util.Optional;
20 import java.util.stream.Collectors;
21
22 import org.jspecify.annotations.Nullable;
23 import org.mybatis.dynamic.sql.common.OrderByModel;
24 import org.mybatis.dynamic.sql.common.OrderByRenderer;
25 import org.mybatis.dynamic.sql.delete.DeleteModel;
26 import org.mybatis.dynamic.sql.render.ExplicitTableAliasCalculator;
27 import org.mybatis.dynamic.sql.render.RenderedParameterInfo;
28 import org.mybatis.dynamic.sql.render.RenderingContext;
29 import org.mybatis.dynamic.sql.render.RenderingStrategy;
30 import org.mybatis.dynamic.sql.render.TableAliasCalculator;
31 import org.mybatis.dynamic.sql.util.FragmentAndParameters;
32 import org.mybatis.dynamic.sql.util.FragmentCollector;
33 import org.mybatis.dynamic.sql.where.EmbeddedWhereModel;
34
35 public class DeleteRenderer {
36 private final DeleteModel deleteModel;
37 private final RenderingContext renderingContext;
38
39 private DeleteRenderer(Builder builder) {
40 deleteModel = Objects.requireNonNull(builder.deleteModel);
41 TableAliasCalculator tableAliasCalculator = builder.deleteModel.tableAlias()
42 .map(a -> ExplicitTableAliasCalculator.of(deleteModel.table(), a))
43 .orElseGet(TableAliasCalculator::empty);
44 renderingContext = RenderingContext
45 .withRenderingStrategy(Objects.requireNonNull(builder.renderingStrategy))
46 .withTableAliasCalculator(tableAliasCalculator)
47 .withStatementConfiguration(deleteModel.statementConfiguration())
48 .build();
49 }
50
51 public DeleteStatementProvider render() {
52 FragmentCollector fragmentCollector = new FragmentCollector();
53
54 fragmentCollector.add(calculateDeleteStatementStart());
55 calculateWhereClause().ifPresent(fragmentCollector::add);
56 calculateOrderByClause().ifPresent(fragmentCollector::add);
57 calculateLimitClause().ifPresent(fragmentCollector::add);
58
59 return toDeleteStatementProvider(fragmentCollector);
60 }
61
62 private DeleteStatementProvider toDeleteStatementProvider(FragmentCollector fragmentCollector) {
63 return DefaultDeleteStatementProvider
64 .withDeleteStatement(fragmentCollector.collectFragments(Collectors.joining(" ")))
65 .withParameters(fragmentCollector.parameters())
66 .build();
67 }
68
69 private FragmentAndParameters calculateDeleteStatementStart() {
70 String aliasedTableName = renderingContext.aliasedTableName(deleteModel.table());
71 return FragmentAndParameters.fromFragment("delete from " + aliasedTableName);
72 }
73
74 private Optional<FragmentAndParameters> calculateWhereClause() {
75 return deleteModel.whereModel().flatMap(this::renderWhereClause);
76 }
77
78 private Optional<FragmentAndParameters> renderWhereClause(EmbeddedWhereModel whereModel) {
79 return whereModel.render(renderingContext);
80 }
81
82 private Optional<FragmentAndParameters> calculateLimitClause() {
83 return deleteModel.limit().map(this::renderLimitClause);
84 }
85
86 private FragmentAndParameters renderLimitClause(Long limit) {
87 RenderedParameterInfo parameterInfo = renderingContext.calculateLimitParameterInfo();
88
89 return FragmentAndParameters.withFragment("limit " + parameterInfo.renderedPlaceHolder())
90 .withParameter(parameterInfo.parameterMapKey(), limit)
91 .build();
92 }
93
94 private Optional<FragmentAndParameters> calculateOrderByClause() {
95 return deleteModel.orderByModel().map(this::renderOrderByClause);
96 }
97
98 private FragmentAndParameters renderOrderByClause(OrderByModel orderByModel) {
99 return new OrderByRenderer(renderingContext).render(orderByModel);
100 }
101
102 public static Builder withDeleteModel(DeleteModel deleteModel) {
103 return new Builder().withDeleteModel(deleteModel);
104 }
105
106 public static class Builder {
107 private @Nullable DeleteModel deleteModel;
108 private @Nullable RenderingStrategy renderingStrategy;
109
110 public Builder withDeleteModel(DeleteModel deleteModel) {
111 this.deleteModel = deleteModel;
112 return this;
113 }
114
115 public Builder withRenderingStrategy(RenderingStrategy renderingStrategy) {
116 this.renderingStrategy = renderingStrategy;
117 return this;
118 }
119
120 public DeleteRenderer build() {
121 return new DeleteRenderer(this);
122 }
123 }
124 }