1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.mybatis.dynamic.sql.update.render;
17
18 import java.util.Objects;
19 import java.util.Optional;
20
21 import org.jspecify.annotations.Nullable;
22 import org.mybatis.dynamic.sql.render.RenderedParameterInfo;
23 import org.mybatis.dynamic.sql.render.RenderingContext;
24 import org.mybatis.dynamic.sql.select.render.SubQueryRenderer;
25 import org.mybatis.dynamic.sql.util.AbstractColumnMapping;
26 import org.mybatis.dynamic.sql.util.ColumnToColumnMapping;
27 import org.mybatis.dynamic.sql.util.ConstantMapping;
28 import org.mybatis.dynamic.sql.util.FragmentAndParameters;
29 import org.mybatis.dynamic.sql.util.NullMapping;
30 import org.mybatis.dynamic.sql.util.SelectMapping;
31 import org.mybatis.dynamic.sql.util.StringConstantMapping;
32 import org.mybatis.dynamic.sql.util.StringUtilities;
33 import org.mybatis.dynamic.sql.util.UpdateMappingVisitor;
34 import org.mybatis.dynamic.sql.util.ValueMapping;
35 import org.mybatis.dynamic.sql.util.ValueOrNullMapping;
36 import org.mybatis.dynamic.sql.util.ValueWhenPresentMapping;
37
38 public class SetPhraseVisitor extends UpdateMappingVisitor<Optional<FragmentAndParameters>> {
39
40 private final RenderingContext renderingContext;
41
42 public SetPhraseVisitor(RenderingContext renderingContext) {
43 this.renderingContext = Objects.requireNonNull(renderingContext);
44 }
45
46 @Override
47 public Optional<FragmentAndParameters> visit(NullMapping mapping) {
48 return buildNullFragment(mapping);
49 }
50
51 @Override
52 public Optional<FragmentAndParameters> visit(ConstantMapping mapping) {
53 String fragment = renderingContext.aliasedColumnName(mapping.column())
54 + " = " + mapping.constant();
55 return FragmentAndParameters.withFragment(fragment)
56 .buildOptional();
57 }
58
59 @Override
60 public Optional<FragmentAndParameters> visit(StringConstantMapping mapping) {
61 String fragment = renderingContext.aliasedColumnName(mapping.column())
62 + " = "
63 + StringUtilities.formatConstantForSQL(mapping.constant());
64
65 return FragmentAndParameters.withFragment(fragment)
66 .buildOptional();
67 }
68
69 @Override
70 public <T> Optional<FragmentAndParameters> visit(ValueMapping<T> mapping) {
71 return buildValueFragment(mapping, mapping.value());
72 }
73
74 @Override
75 public <T> Optional<FragmentAndParameters> visit(ValueOrNullMapping<T> mapping) {
76 return mapping.value()
77 .map(v -> buildValueFragment(mapping, v))
78 .orElseGet(() -> buildNullFragment(mapping));
79 }
80
81 @Override
82 public <T> Optional<FragmentAndParameters> visit(ValueWhenPresentMapping<T> mapping) {
83 return mapping.value().flatMap(v -> buildValueFragment(mapping, v));
84 }
85
86 @Override
87 public Optional<FragmentAndParameters> visit(SelectMapping mapping) {
88 String prefix = renderingContext.aliasedColumnName(mapping.column()) + " = (";
89
90 FragmentAndParameters fragmentAndParameters = SubQueryRenderer.withSelectModel(mapping.selectModel())
91 .withRenderingContext(renderingContext)
92 .withPrefix(prefix)
93 .withSuffix(")")
94 .build()
95 .render();
96
97 return Optional.of(fragmentAndParameters);
98 }
99
100 @Override
101 public Optional<FragmentAndParameters> visit(ColumnToColumnMapping mapping) {
102 FragmentAndParameters fragmentAndParameters = mapping.rightColumn().render(renderingContext)
103 .mapFragment(f -> renderingContext.aliasedColumnName(mapping.column()) + " = " + f);
104 return Optional.of(fragmentAndParameters);
105 }
106
107 private <T> Optional<FragmentAndParameters> buildValueFragment(AbstractColumnMapping mapping, @Nullable T value) {
108 RenderedParameterInfo parameterInfo = renderingContext.calculateParameterInfo(mapping.column());
109 String setPhrase = renderingContext.aliasedColumnName(mapping.column())
110 + " = "
111 + parameterInfo.renderedPlaceHolder();
112
113 return FragmentAndParameters.withFragment(setPhrase)
114 .withParameter(parameterInfo.parameterMapKey(), value)
115 .buildOptional();
116 }
117
118 private Optional<FragmentAndParameters> buildNullFragment(AbstractColumnMapping mapping) {
119 return FragmentAndParameters
120 .withFragment(renderingContext.aliasedColumnName(mapping.column()) + " = null")
121 .buildOptional();
122 }
123 }