1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.mybatis.dynamic.sql.select.render;
17
18 import java.util.Objects;
19 import java.util.stream.Collectors;
20
21 import org.jspecify.annotations.Nullable;
22 import org.mybatis.dynamic.sql.common.OrderByModel;
23 import org.mybatis.dynamic.sql.common.OrderByRenderer;
24 import org.mybatis.dynamic.sql.render.RenderingContext;
25 import org.mybatis.dynamic.sql.select.PagingModel;
26 import org.mybatis.dynamic.sql.select.QueryExpressionModel;
27 import org.mybatis.dynamic.sql.select.SelectModel;
28 import org.mybatis.dynamic.sql.util.FragmentAndParameters;
29 import org.mybatis.dynamic.sql.util.FragmentCollector;
30
31 public class SubQueryRenderer {
32 private final SelectModel selectModel;
33 private final RenderingContext renderingContext;
34 private final String prefix;
35 private final String suffix;
36
37 private SubQueryRenderer(Builder builder) {
38 selectModel = Objects.requireNonNull(builder.selectModel);
39 renderingContext = Objects.requireNonNull(builder.renderingContext);
40 prefix = builder.prefix == null ? "" : builder.prefix;
41 suffix = builder.suffix == null ? "" : builder.suffix;
42 }
43
44 public FragmentAndParameters render() {
45 FragmentCollector fragmentCollector = selectModel
46 .queryExpressions()
47 .map(this::renderQueryExpression)
48 .collect(FragmentCollector.collect());
49
50 selectModel.orderByModel()
51 .map(this::renderOrderBy)
52 .ifPresent(fragmentCollector::add);
53
54 selectModel.pagingModel()
55 .map(this::renderPagingModel)
56 .ifPresent(fragmentCollector::add);
57
58 selectModel.forClause()
59 .map(FragmentAndParameters::fromFragment)
60 .ifPresent(fragmentCollector::add);
61
62 selectModel.waitClause()
63 .map(FragmentAndParameters::fromFragment)
64 .ifPresent(fragmentCollector::add);
65
66 return fragmentCollector.toFragmentAndParameters(Collectors.joining(" ", prefix, suffix));
67 }
68
69 private FragmentAndParameters renderQueryExpression(QueryExpressionModel queryExpressionModel) {
70 return QueryExpressionRenderer.withQueryExpression(queryExpressionModel)
71 .withRenderingContext(renderingContext)
72 .build()
73 .render();
74 }
75
76 private FragmentAndParameters renderOrderBy(OrderByModel orderByModel) {
77 return new OrderByRenderer(renderingContext).render(orderByModel);
78 }
79
80 private FragmentAndParameters renderPagingModel(PagingModel pagingModel) {
81 return new PagingModelRenderer.Builder()
82 .withPagingModel(pagingModel)
83 .withRenderingContext(renderingContext)
84 .build()
85 .render();
86 }
87
88 public static Builder withSelectModel(SelectModel selectModel) {
89 return new Builder().withSelectModel(selectModel);
90 }
91
92 public static class Builder {
93 private @Nullable SelectModel selectModel;
94 private @Nullable RenderingContext renderingContext;
95 private @Nullable String prefix;
96 private @Nullable String suffix;
97
98 public Builder withRenderingContext(RenderingContext renderingContext) {
99 this.renderingContext = renderingContext;
100 return this;
101 }
102
103 public Builder withSelectModel(SelectModel selectModel) {
104 this.selectModel = selectModel;
105 return this;
106 }
107
108 public Builder withPrefix(String prefix) {
109 this.prefix = prefix;
110 return this;
111 }
112
113 public Builder withSuffix(String suffix) {
114 this.suffix = suffix;
115 return this;
116 }
117
118 public SubQueryRenderer build() {
119 return new SubQueryRenderer(this);
120 }
121 }
122 }