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

mybatis / ibatis-2 / 733

29 Dec 2025 12:15AM UTC coverage: 65.571% (-0.03%) from 65.597%
733

Pull #338

github

web-flow
Merge abffa4d0e into adb99ac51
Pull Request #338: Various statement syntax cleanup

1598 of 2797 branches covered (57.13%)

207 of 278 new or added lines in 7 files covered. (74.46%)

3 existing lines in 3 files now uncovered.

5047 of 7697 relevant lines covered (65.57%)

0.66 hits per line

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

72.85
/src/main/java/com/ibatis/sqlmap/engine/mapping/parameter/InlineParameterMapParser.java
1
/*
2
 * Copyright 2004-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 com.ibatis.sqlmap.engine.mapping.parameter;
17

18
import com.ibatis.common.beans.Probe;
19
import com.ibatis.common.beans.ProbeFactory;
20
import com.ibatis.common.resources.Resources;
21
import com.ibatis.sqlmap.client.SqlMapException;
22
import com.ibatis.sqlmap.client.extensions.TypeHandlerCallback;
23
import com.ibatis.sqlmap.engine.mapping.sql.SqlText;
24
import com.ibatis.sqlmap.engine.type.CustomTypeHandler;
25
import com.ibatis.sqlmap.engine.type.DomTypeMarker;
26
import com.ibatis.sqlmap.engine.type.TypeHandler;
27
import com.ibatis.sqlmap.engine.type.TypeHandlerFactory;
28

29
import java.util.ArrayList;
30
import java.util.List;
31
import java.util.StringTokenizer;
32

33
/**
34
 * The Class InlineParameterMapParser.
35
 */
36
public class InlineParameterMapParser {
1✔
37

38
  /** The Constant PROBE. */
39
  private static final Probe PROBE = ProbeFactory.getProbe();
1✔
40

41
  /** The Constant PARAMETER_TOKEN. */
42
  private static final String PARAMETER_TOKEN = "#";
43

44
  /** The Constant PARAM_DELIM. */
45
  private static final String PARAM_DELIM = ":";
46

47
  /**
48
   * Parses the inline parameter map.
49
   *
50
   * @param typeHandlerFactory
51
   *          the type handler factory
52
   * @param sqlStatement
53
   *          the sql statement
54
   *
55
   * @return the sql text
56
   */
57
  public SqlText parseInlineParameterMap(TypeHandlerFactory typeHandlerFactory, String sqlStatement) {
58
    return parseInlineParameterMap(typeHandlerFactory, sqlStatement, null);
1✔
59
  }
60

61
  /**
62
   * Parses the inline parameter map.
63
   *
64
   * @param typeHandlerFactory
65
   *          the type handler factory
66
   * @param sqlStatement
67
   *          the sql statement
68
   * @param parameterClass
69
   *          the parameter class
70
   *
71
   * @return the sql text
72
   */
73
  public SqlText parseInlineParameterMap(TypeHandlerFactory typeHandlerFactory, String sqlStatement,
74
      Class parameterClass) {
75

76
    String newSql = sqlStatement;
1✔
77

78
    List mappingList = new ArrayList<>();
1✔
79

80
    StringTokenizer parser = new StringTokenizer(sqlStatement, PARAMETER_TOKEN, true);
1✔
81
    StringBuilder newSqlBuffer = new StringBuilder();
1✔
82

83
    String token = null;
1✔
84
    String lastToken = null;
1✔
85
    while (parser.hasMoreTokens()) {
1✔
86
      token = parser.nextToken();
1✔
87
      if (PARAMETER_TOKEN.equals(lastToken)) {
1✔
88
        if (PARAMETER_TOKEN.equals(token)) {
1!
89
          newSqlBuffer.append(PARAMETER_TOKEN);
×
90
          token = null;
×
91
        } else {
92
          ParameterMapping mapping = null;
1✔
93
          if (token.indexOf(PARAM_DELIM) > -1) {
1✔
94
            mapping = oldParseMapping(token, parameterClass, typeHandlerFactory);
1✔
95
          } else {
96
            mapping = newParseMapping(token, parameterClass, typeHandlerFactory);
1✔
97
          }
98

99
          mappingList.add(mapping);
1✔
100
          newSqlBuffer.append("?");
1✔
101
          boolean hasMoreTokens = parser.hasMoreTokens();
1✔
102
          if (hasMoreTokens) {
1✔
103
            token = parser.nextToken();
1✔
104
          }
105
          if (!hasMoreTokens || !PARAMETER_TOKEN.equals(token)) {
1!
106
            throw new SqlMapException(
1✔
107
                "Unterminated inline parameter in mapped statement near '" + newSqlBuffer.toString() + "'");
1✔
108
          }
109
          token = null;
1✔
110
        }
1✔
111
      } else if (!PARAMETER_TOKEN.equals(token)) {
1✔
112
        newSqlBuffer.append(token);
1✔
113
      }
114

115
      lastToken = token;
1✔
116
    }
117

118
    newSql = newSqlBuffer.toString();
1✔
119

120
    ParameterMapping[] mappingArray = (ParameterMapping[]) mappingList
1✔
121
        .toArray(new ParameterMapping[mappingList.size()]);
1✔
122

123
    SqlText sqlText = new SqlText();
1✔
124
    sqlText.setText(newSql);
1✔
125
    sqlText.setParameterMappings(mappingArray);
1✔
126
    return sqlText;
1✔
127
  }
128

129
  /**
130
   * New parse mapping.
131
   *
132
   * @param token
133
   *          the token
134
   * @param parameterClass
135
   *          the parameter class
136
   * @param typeHandlerFactory
137
   *          the type handler factory
138
   *
139
   * @return the parameter mapping
140
   */
141
  private ParameterMapping newParseMapping(String token, Class parameterClass, TypeHandlerFactory typeHandlerFactory) {
142
    ParameterMapping mapping = new ParameterMapping();
1✔
143

144
    // #propertyName,javaType=string,jdbcType=VARCHAR,mode=IN,nullValue=N/A,handler=string,numericScale=2#
145

146
    StringTokenizer paramParser = new StringTokenizer(token, "=,", false);
1✔
147
    mapping.setPropertyName(paramParser.nextToken());
1✔
148

149
    while (paramParser.hasMoreTokens()) {
1✔
150
      String field = paramParser.nextToken();
1✔
151
      if (!paramParser.hasMoreTokens()) {
1!
NEW
152
        throw new SqlMapException("Incorrect inline parameter map format (missmatched name=value pairs): " + token);
×
153
      }
154
      String value = paramParser.nextToken();
1✔
155
      if (field != null) {
1!
156
        switch (field) {
1!
157
          case "javaType":
158
            value = typeHandlerFactory.resolveAlias(value);
1✔
159
            mapping.setJavaTypeName(value);
1✔
160
            break;
1✔
161
          case "jdbcType":
162
            mapping.setJdbcTypeName(value);
1✔
163
            break;
1✔
164
          case "mode":
NEW
165
            mapping.setMode(value);
×
NEW
166
            break;
×
167
          case "nullValue":
168
            mapping.setNullValue(value);
1✔
169
            break;
1✔
170
          case "handler":
171
            try {
NEW
172
              value = typeHandlerFactory.resolveAlias(value);
×
NEW
173
              Object impl = Resources.instantiate(value);
×
NEW
174
              if (impl instanceof TypeHandlerCallback) {
×
NEW
175
                mapping.setTypeHandler(new CustomTypeHandler((TypeHandlerCallback) impl));
×
NEW
176
              } else if (impl instanceof TypeHandler) {
×
NEW
177
                mapping.setTypeHandler((TypeHandler) impl);
×
178
              } else {
NEW
179
                throw new SqlMapException(
×
180
                    "The class " + value + " is not a valid implementation of TypeHandler or TypeHandlerCallback");
181
              }
NEW
182
            } catch (Exception e) {
×
NEW
183
              throw new SqlMapException("Error loading class specified by handler field in " + token + ".  Cause: " + e,
×
184
                  e);
185
            }
×
186
            break;
187
          case "numericScale":
188
            try {
NEW
189
              Integer numericScale = Integer.valueOf(value);
×
NEW
190
              if (numericScale.intValue() < 0) {
×
NEW
191
                throw new SqlMapException("Value specified for numericScale must be greater than or equal to zero");
×
192
              }
NEW
193
              mapping.setNumericScale(numericScale);
×
NEW
194
            } catch (NumberFormatException e) {
×
NEW
195
              throw new SqlMapException("Value specified for numericScale is not a valid Integer");
×
196
            }
×
197
            break;
198
          default:
NEW
199
            throw new SqlMapException("Unrecognized parameter mapping field: '" + field + "' in " + token);
×
200
        }
1✔
201
      } else {
NEW
202
        throw new SqlMapException("Unrecognized parameter mapping field: '" + field + "' in " + token);
×
203
      }
204
    }
1✔
205

206
    if (mapping.getTypeHandler() == null) {
1!
207
      TypeHandler handler;
208
      if (parameterClass == null) {
1✔
209
        handler = typeHandlerFactory.getUnkownTypeHandler();
1✔
210
      } else {
211
        handler = resolveTypeHandler(typeHandlerFactory, parameterClass, mapping.getPropertyName(),
1✔
212
            mapping.getJavaTypeName(), mapping.getJdbcTypeName());
1✔
213
      }
214
      mapping.setTypeHandler(handler);
1✔
215
    }
216

217
    return mapping;
1✔
218
  }
219

220
  /**
221
   * Old parse mapping.
222
   *
223
   * @param token
224
   *          the token
225
   * @param parameterClass
226
   *          the parameter class
227
   * @param typeHandlerFactory
228
   *          the type handler factory
229
   *
230
   * @return the parameter mapping
231
   */
232
  private ParameterMapping oldParseMapping(String token, Class parameterClass, TypeHandlerFactory typeHandlerFactory) {
233
    ParameterMapping mapping = new ParameterMapping();
1✔
234
    if (token.indexOf(PARAM_DELIM) <= -1) {
1!
UNCOV
235
      mapping.setPropertyName(token);
×
236
      TypeHandler handler;
237
      if (parameterClass == null) {
×
238
        handler = typeHandlerFactory.getUnkownTypeHandler();
×
239
      } else {
240
        handler = resolveTypeHandler(typeHandlerFactory, parameterClass, token, null, null);
×
241
      }
242
      mapping.setTypeHandler(handler);
×
243
      return mapping;
×
244
    }
245
    StringTokenizer paramParser = new StringTokenizer(token, PARAM_DELIM, true);
1✔
246
    int n1 = paramParser.countTokens();
1✔
247
    if (n1 == 3) {
1✔
248
      String name = paramParser.nextToken();
1✔
249
      paramParser.nextToken(); // ignore ":"
1✔
250
      String type = paramParser.nextToken();
1✔
251
      mapping.setPropertyName(name);
1✔
252
      mapping.setJdbcTypeName(type);
1✔
253
      TypeHandler handler;
254
      if (parameterClass == null) {
1✔
255
        handler = typeHandlerFactory.getUnkownTypeHandler();
1✔
256
      } else {
257
        handler = resolveTypeHandler(typeHandlerFactory, parameterClass, name, null, type);
1✔
258
      }
259
      mapping.setTypeHandler(handler);
1✔
260
      return mapping;
1✔
261
    } else if (n1 >= 5) {
1!
262
      String name = paramParser.nextToken();
1✔
263
      paramParser.nextToken(); // ignore ":"
1✔
264
      String type = paramParser.nextToken();
1✔
265
      paramParser.nextToken(); // ignore ":"
1✔
266
      StringBuilder nullValue = new StringBuilder().append(paramParser.nextToken());
1✔
267
      while (paramParser.hasMoreTokens()) {
1!
NEW
268
        nullValue.append(paramParser.nextToken());
×
269
      }
270
      mapping.setPropertyName(name);
1✔
271
      mapping.setJdbcTypeName(type);
1✔
272
      mapping.setNullValue(nullValue.toString());
1✔
273
      TypeHandler handler;
274
      if (parameterClass == null) {
1✔
275
        handler = typeHandlerFactory.getUnkownTypeHandler();
1✔
276
      } else {
277
        handler = resolveTypeHandler(typeHandlerFactory, parameterClass, name, null, type);
1✔
278
      }
279
      mapping.setTypeHandler(handler);
1✔
280
      return mapping;
1✔
281
    } else {
NEW
282
      throw new SqlMapException("Incorrect inline parameter map format: " + token);
×
283
    }
284
  }
285

286
  /**
287
   * Resolve type handler.
288
   *
289
   * @param typeHandlerFactory
290
   *          the type handler factory
291
   * @param clazz
292
   *          the clazz
293
   * @param propertyName
294
   *          the property name
295
   * @param javaType
296
   *          the java type
297
   * @param jdbcType
298
   *          the jdbc type
299
   *
300
   * @return the type handler
301
   */
302
  private TypeHandler resolveTypeHandler(TypeHandlerFactory typeHandlerFactory, Class clazz, String propertyName,
303
      String javaType, String jdbcType) {
304
    TypeHandler handler = null;
1✔
305
    if (clazz == null) {
1!
306
      // Unknown
307
      handler = typeHandlerFactory.getUnkownTypeHandler();
×
308
    } else if (DomTypeMarker.class.isAssignableFrom(clazz)) {
1✔
309
      // DOM
310
      handler = typeHandlerFactory.getTypeHandler(String.class, jdbcType);
1✔
311
    } else if (java.util.Map.class.isAssignableFrom(clazz)) {
1✔
312
      // Map
313
      if (javaType == null) {
1!
314
        handler = typeHandlerFactory.getUnkownTypeHandler();
1✔
315
        // BUG 1012591 -
316
        // typeHandlerFactory.getTypeHandler(java.lang.Object.class,
317
        // jdbcType);
318
      } else {
319
        try {
320
          javaType = typeHandlerFactory.resolveAlias(javaType);
×
321
          Class javaClass = Resources.classForName(javaType);
×
322
          handler = typeHandlerFactory.getTypeHandler(javaClass, jdbcType);
×
323
        } catch (Exception e) {
×
324
          throw new SqlMapException("Error.  Could not set TypeHandler.  Cause: " + e, e);
×
325
        }
×
326
      }
327
    } else if (typeHandlerFactory.getTypeHandler(clazz, jdbcType) != null) {
1✔
328
      // Primitive
329
      handler = typeHandlerFactory.getTypeHandler(clazz, jdbcType);
1✔
330
    } else {
331
      // JavaBean
332
      if (javaType == null) {
1✔
333

334
        Class type = PROBE.getPropertyTypeForGetter(clazz, propertyName);
1✔
335
        handler = typeHandlerFactory.getTypeHandler(type, jdbcType);
1✔
336

337
      } else {
1✔
338
        try {
339
          javaType = typeHandlerFactory.resolveAlias(javaType);
1✔
340
          Class javaClass = Resources.classForName(javaType);
1✔
341
          handler = typeHandlerFactory.getTypeHandler(javaClass, jdbcType);
1✔
342
        } catch (Exception e) {
×
343
          throw new SqlMapException("Error.  Could not set TypeHandler.  Cause: " + e, e);
×
344
        }
1✔
345
      }
346
    }
347
    return handler;
1✔
348
  }
349

350
}
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