• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mybatis / mybatis-3 / 2604

03 Jan 2025 10:00AM UTC coverage: 87.524% (+0.3%) from 87.177%
2604

Pull #3146

github

web-flow
Merge 60c1f5fea into 8ac3920af
Pull Request #3146: Shared ambiguity instance

3633 of 4401 branches covered (82.55%)

4 of 4 new or added lines in 1 file covered. (100.0%)

254 existing lines in 22 files now uncovered.

9569 of 10933 relevant lines covered (87.52%)

0.88 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.67
/src/main/java/org/apache/ibatis/builder/SqlSourceBuilder.java
1
/*
2
 *    Copyright 2009-2024 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.apache.ibatis.builder;
17

18
import java.sql.ResultSet;
19
import java.util.ArrayList;
20
import java.util.List;
21
import java.util.Map;
22
import java.util.StringTokenizer;
23

24
import org.apache.ibatis.mapping.ParameterMapping;
25
import org.apache.ibatis.mapping.SqlSource;
26
import org.apache.ibatis.parsing.GenericTokenParser;
27
import org.apache.ibatis.parsing.TokenHandler;
28
import org.apache.ibatis.reflection.MetaClass;
29
import org.apache.ibatis.reflection.MetaObject;
30
import org.apache.ibatis.session.Configuration;
31
import org.apache.ibatis.type.JdbcType;
32

33
/**
34
 * @author Clinton Begin
35
 */
36
public class SqlSourceBuilder extends BaseBuilder {
37

38
  private static final String PARAMETER_PROPERTIES = "javaType,jdbcType,mode,numericScale,resultMap,typeHandler,jdbcTypeName";
39

40
  public SqlSourceBuilder(Configuration configuration) {
41
    super(configuration);
1✔
42
  }
1✔
43

44
  public SqlSource parse(String originalSql, Class<?> parameterType, Map<String, Object> additionalParameters) {
45
    ParameterMappingTokenHandler handler = new ParameterMappingTokenHandler(configuration, parameterType,
1✔
46
        additionalParameters);
47
    GenericTokenParser parser = new GenericTokenParser("#{", "}", handler);
1✔
48
    String sql;
49
    if (configuration.isShrinkWhitespacesInSql()) {
1✔
50
      sql = parser.parse(removeExtraWhitespaces(originalSql));
1✔
51
    } else {
52
      sql = parser.parse(originalSql);
1✔
53
    }
54
    return new StaticSqlSource(configuration, sql, handler.getParameterMappings());
1✔
55
  }
56

57
  public static String removeExtraWhitespaces(String original) {
58
    StringTokenizer tokenizer = new StringTokenizer(original);
1✔
59
    StringBuilder builder = new StringBuilder();
1✔
60
    boolean hasMoreTokens = tokenizer.hasMoreTokens();
1✔
61
    while (hasMoreTokens) {
1✔
62
      builder.append(tokenizer.nextToken());
1✔
63
      hasMoreTokens = tokenizer.hasMoreTokens();
1✔
64
      if (hasMoreTokens) {
1✔
65
        builder.append(' ');
1✔
66
      }
67
    }
68
    return builder.toString();
1✔
69
  }
70

71
  private static class ParameterMappingTokenHandler extends BaseBuilder implements TokenHandler {
72

73
    private final List<ParameterMapping> parameterMappings = new ArrayList<>();
1✔
74
    private final Class<?> parameterType;
75
    private final MetaObject metaParameters;
76

77
    public ParameterMappingTokenHandler(Configuration configuration, Class<?> parameterType,
78
        Map<String, Object> additionalParameters) {
79
      super(configuration);
1✔
80
      this.parameterType = parameterType;
1✔
81
      this.metaParameters = configuration.newMetaObject(additionalParameters);
1✔
82
    }
1✔
83

84
    public List<ParameterMapping> getParameterMappings() {
85
      return parameterMappings;
1✔
86
    }
87

88
    @Override
89
    public String handleToken(String content) {
90
      parameterMappings.add(buildParameterMapping(content));
1✔
91
      return "?";
1✔
92
    }
93

94
    private ParameterMapping buildParameterMapping(String content) {
95
      Map<String, String> propertiesMap = parseParameterMapping(content);
1✔
96
      String property = propertiesMap.get("property");
1✔
97
      Class<?> propertyType;
98
      if (metaParameters.hasGetter(property)) { // issue #448 get type from additional params
1✔
99
        propertyType = metaParameters.getGetterType(property);
1✔
100
      } else if (typeHandlerRegistry.hasTypeHandler(parameterType)) {
1✔
101
        propertyType = parameterType;
1✔
102
      } else if (JdbcType.CURSOR.name().equals(propertiesMap.get("jdbcType"))) {
1!
UNCOV
103
        propertyType = ResultSet.class;
×
104
      } else if (property == null || Map.class.isAssignableFrom(parameterType)) {
1!
105
        propertyType = Object.class;
1✔
106
      } else {
107
        MetaClass metaClass = MetaClass.forClass(parameterType, configuration.getReflectorFactory());
1✔
108
        if (metaClass.hasGetter(property)) {
1✔
109
          propertyType = metaClass.getGetterType(property);
1✔
110
        } else {
111
          propertyType = Object.class;
1✔
112
        }
113
      }
114
      ParameterMapping.Builder builder = new ParameterMapping.Builder(configuration, property, propertyType);
1✔
115
      Class<?> javaType = propertyType;
1✔
116
      String typeHandlerAlias = null;
1✔
117
      for (Map.Entry<String, String> entry : propertiesMap.entrySet()) {
1✔
118
        String name = entry.getKey();
1✔
119
        String value = entry.getValue();
1✔
120
        if ("javaType".equals(name)) {
1✔
121
          javaType = resolveClass(value);
1✔
122
          builder.javaType(javaType);
1✔
123
        } else if ("jdbcType".equals(name)) {
1✔
124
          builder.jdbcType(resolveJdbcType(value));
1✔
125
        } else if ("mode".equals(name)) {
1✔
126
          builder.mode(resolveParameterMode(value));
1✔
127
        } else if ("numericScale".equals(name)) {
1!
UNCOV
128
          builder.numericScale(Integer.valueOf(value));
×
129
        } else if ("resultMap".equals(name)) {
1!
UNCOV
130
          builder.resultMapId(value);
×
131
        } else if ("typeHandler".equals(name)) {
1✔
132
          typeHandlerAlias = value;
1✔
133
        } else if ("jdbcTypeName".equals(name)) {
1!
UNCOV
134
          builder.jdbcTypeName(value);
×
135
        } else if ("property".equals(name)) {
1!
136
          // Do Nothing
137
        } else if ("expression".equals(name)) {
×
UNCOV
138
          throw new BuilderException("Expression based parameters are not supported yet");
×
139
        } else {
UNCOV
140
          throw new BuilderException("An invalid property '" + name + "' was found in mapping #{" + content
×
141
              + "}.  Valid properties are " + PARAMETER_PROPERTIES);
142
        }
143
      }
1✔
144
      if (typeHandlerAlias != null) {
1✔
145
        builder.typeHandler(resolveTypeHandler(javaType, typeHandlerAlias));
1✔
146
      }
147
      return builder.build();
1✔
148
    }
149

150
    private Map<String, String> parseParameterMapping(String content) {
151
      try {
152
        return new ParameterExpression(content);
1✔
153
      } catch (BuilderException ex) {
×
UNCOV
154
        throw ex;
×
155
      } catch (Exception ex) {
1✔
156
        throw new BuilderException("Parsing error was found in mapping #{" + content
1✔
157
            + "}.  Check syntax #{property|(expression), var1=value1, var2=value2, ...} ", ex);
158
      }
159
    }
160
  }
161

162
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc