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;
17  
18  import java.sql.JDBCType;
19  import java.util.Objects;
20  import java.util.Optional;
21  
22  import org.jspecify.annotations.Nullable;
23  import org.mybatis.dynamic.sql.render.RenderingContext;
24  import org.mybatis.dynamic.sql.util.FragmentAndParameters;
25  
26  /**
27   * A derived column is a column that is not directly related to a table. This is primarily
28   * used for supporting sub-queries. The main difference in this class and {@link SqlColumn} is
29   * that this class does not have a related {@link SqlTable} and therefore ignores any table
30   * qualifier set in a query. If a table qualifier is required it can be set directly in the
31   * builder for this class.
32   *
33   * @param <T>
34   *            The Java type that corresponds to this column - not used except for compiler type checking for conditions
35   */
36  public class DerivedColumn<T> implements BindableColumn<T> {
37      private final String name;
38      private final @Nullable String tableQualifier;
39      private final @Nullable String columnAlias;
40      private final @Nullable JDBCType jdbcType;
41      private final @Nullable String typeHandler;
42  
43      protected DerivedColumn(Builder<T> builder) {
44          this.name = Objects.requireNonNull(builder.name);
45          this.tableQualifier = builder.tableQualifier;
46          this.columnAlias = builder.columnAlias;
47          this.jdbcType = builder.jdbcType;
48          this.typeHandler = builder.typeHandler;
49      }
50  
51      @Override
52      public Optional<String> alias() {
53          return Optional.ofNullable(columnAlias);
54      }
55  
56      @Override
57      public Optional<JDBCType> jdbcType() {
58          return Optional.ofNullable(jdbcType);
59      }
60  
61      @Override
62      public Optional<String> typeHandler() {
63          return Optional.ofNullable(typeHandler);
64      }
65  
66      @Override
67      public FragmentAndParameters render(RenderingContext renderingContext) {
68          String fragment = tableQualifier == null ? name : tableQualifier + "." + name; //$NON-NLS-1$
69          return FragmentAndParameters.fromFragment(fragment);
70      }
71  
72      @Override
73      public DerivedColumn<T> as(String columnAlias) {
74          return new Builder<T>()
75                  .withName(name)
76                  .withColumnAlias(columnAlias)
77                  .withJdbcType(jdbcType)
78                  .withTypeHandler(typeHandler)
79                  .withTableQualifier(tableQualifier)
80                  .build();
81      }
82  
83      public static <T> DerivedColumn<T> of(String name) {
84          return new Builder<T>()
85                  .withName(name)
86                  .build();
87      }
88  
89      public static <T> DerivedColumn<T> of(String name, String tableQualifier) {
90          return new Builder<T>()
91                  .withName(name)
92                  .withTableQualifier(tableQualifier)
93                  .build();
94      }
95  
96      public static class Builder<T> {
97          private @Nullable String name;
98          private @Nullable String tableQualifier;
99          private @Nullable String columnAlias;
100         private @Nullable JDBCType jdbcType;
101         private @Nullable String typeHandler;
102 
103         public Builder<T> withName(String name) {
104             this.name = name;
105             return this;
106         }
107 
108         public Builder<T> withTableQualifier(@Nullable String tableQualifier) {
109             this.tableQualifier = tableQualifier;
110             return this;
111         }
112 
113         public Builder<T> withColumnAlias(String columnAlias) {
114             this.columnAlias = columnAlias;
115             return this;
116         }
117 
118         public Builder<T> withJdbcType(@Nullable JDBCType jdbcType) {
119             this.jdbcType = jdbcType;
120             return this;
121         }
122 
123         public Builder<T> withTypeHandler(@Nullable String typeHandler) {
124             this.typeHandler = typeHandler;
125             return this;
126         }
127 
128         public DerivedColumn<T> build() {
129             return new DerivedColumn<>(this);
130         }
131     }
132 }