Skip to content

Commit d1f5ee2

Browse files
committed
Avoid NPE for anonymous SqlParameter in CallMetaDataContext
Issue: SPR-13628 (cherry picked from commit 6685c78)
1 parent 0f4e4fc commit d1f5ee2

File tree

1 file changed

+61
-55
lines changed

1 file changed

+61
-55
lines changed

spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallMetaDataContext.java

+61-55
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -280,88 +280,94 @@ public void processParameters(List<SqlParameter> parameters) {
280280
* Reconcile the provided parameters with available metadata and add new ones where appropriate.
281281
*/
282282
protected List<SqlParameter> reconcileParameters(List<SqlParameter> parameters) {
283-
final List<SqlParameter> declaredReturnParameters = new ArrayList<SqlParameter>();
284-
final Map<String, SqlParameter> declaredParameters = new LinkedHashMap<String, SqlParameter>();
283+
final List<SqlParameter> declaredReturnParams = new ArrayList<SqlParameter>();
284+
final Map<String, SqlParameter> declaredParams = new LinkedHashMap<String, SqlParameter>();
285285
boolean returnDeclared = false;
286-
List<String> outParameterNames = new ArrayList<String>();
287-
List<String> metaDataParameterNames = new ArrayList<String>();
286+
List<String> outParamNames = new ArrayList<String>();
287+
List<String> metaDataParamNames = new ArrayList<String>();
288288

289289
// Get the names of the meta data parameters
290290
for (CallParameterMetaData meta : this.metaDataProvider.getCallParameterMetaData()) {
291291
if (meta.getParameterType() != DatabaseMetaData.procedureColumnReturn) {
292-
metaDataParameterNames.add(meta.getParameterName().toLowerCase());
292+
metaDataParamNames.add(meta.getParameterName().toLowerCase());
293293
}
294294
}
295295

296296
// Separate implicit return parameters from explicit parameters...
297-
for (SqlParameter parameter : parameters) {
298-
if (parameter.isResultsParameter()) {
299-
declaredReturnParameters.add(parameter);
297+
for (SqlParameter param : parameters) {
298+
if (param.isResultsParameter()) {
299+
declaredReturnParams.add(param);
300300
}
301301
else {
302-
String parameterNameToMatch = this.metaDataProvider.parameterNameToUse(parameter.getName()).toLowerCase();
303-
declaredParameters.put(parameterNameToMatch, parameter);
304-
if (parameter instanceof SqlOutParameter) {
305-
outParameterNames.add(parameter.getName());
306-
if (isFunction() && !metaDataParameterNames.contains(parameterNameToMatch)) {
302+
String paramName = param.getName();
303+
if (paramName == null) {
304+
throw new IllegalArgumentException("Anonymous parameters not supported for calls - " +
305+
"please specify a name for the parameter of SQL type " + param.getSqlType());
306+
}
307+
String paramNameToMatch = this.metaDataProvider.parameterNameToUse(paramName).toLowerCase();
308+
declaredParams.put(paramNameToMatch, param);
309+
if (param instanceof SqlOutParameter) {
310+
outParamNames.add(paramName);
311+
if (isFunction() && !metaDataParamNames.contains(paramNameToMatch)) {
307312
if (!returnDeclared) {
308313
if (logger.isDebugEnabled()) {
309-
logger.debug("Using declared out parameter '" + parameter.getName() + "' for function return value");
314+
logger.debug("Using declared out parameter '" + paramName +
315+
"' for function return value");
310316
}
311-
setFunctionReturnName(parameter.getName());
317+
setFunctionReturnName(paramName);
312318
returnDeclared = true;
313319
}
314320
}
315321
}
316322
}
317323
}
318-
setOutParameterNames(outParameterNames);
324+
setOutParameterNames(outParamNames);
319325

320-
List<SqlParameter> workParameters = new ArrayList<SqlParameter>();
321-
workParameters.addAll(declaredReturnParameters);
326+
List<SqlParameter> workParams = new ArrayList<SqlParameter>();
327+
workParams.addAll(declaredReturnParams);
322328

323329
if (!this.metaDataProvider.isProcedureColumnMetaDataUsed()) {
324-
workParameters.addAll(declaredParameters.values());
325-
return workParameters;
330+
workParams.addAll(declaredParams.values());
331+
return workParams;
326332
}
327333

328334
Map<String, String> limitedInParamNamesMap = new HashMap<String, String>(this.limitedInParameterNames.size());
329-
for (String limitedParameterName : this.limitedInParameterNames) {
335+
for (String limitedParamName : this.limitedInParameterNames) {
330336
limitedInParamNamesMap.put(
331-
this.metaDataProvider.parameterNameToUse(limitedParameterName).toLowerCase(), limitedParameterName);
337+
this.metaDataProvider.parameterNameToUse(limitedParamName).toLowerCase(), limitedParamName);
332338
}
333339

334340
for (CallParameterMetaData meta : this.metaDataProvider.getCallParameterMetaData()) {
335-
String parNameToCheck = null;
341+
String paramNameToCheck = null;
336342
if (meta.getParameterName() != null) {
337-
parNameToCheck = this.metaDataProvider.parameterNameToUse(meta.getParameterName()).toLowerCase();
343+
paramNameToCheck = this.metaDataProvider.parameterNameToUse(meta.getParameterName()).toLowerCase();
338344
}
339-
String parNameToUse = this.metaDataProvider.parameterNameToUse(meta.getParameterName());
340-
if (declaredParameters.containsKey(parNameToCheck) ||
345+
String paramNameToUse = this.metaDataProvider.parameterNameToUse(meta.getParameterName());
346+
if (declaredParams.containsKey(paramNameToCheck) ||
341347
(meta.getParameterType() == DatabaseMetaData.procedureColumnReturn && returnDeclared)) {
342-
SqlParameter parameter;
348+
SqlParameter param;
343349
if (meta.getParameterType() == DatabaseMetaData.procedureColumnReturn) {
344-
parameter = declaredParameters.get(getFunctionReturnName());
345-
if (parameter == null && getOutParameterNames().size() > 0) {
346-
parameter = declaredParameters.get(getOutParameterNames().get(0).toLowerCase());
350+
param = declaredParams.get(getFunctionReturnName());
351+
if (param == null && getOutParameterNames().size() > 0) {
352+
param = declaredParams.get(getOutParameterNames().get(0).toLowerCase());
347353
}
348-
if (parameter == null) {
354+
if (param == null) {
349355
throw new InvalidDataAccessApiUsageException(
350356
"Unable to locate declared parameter for function return value - " +
351-
" add a SqlOutParameter with name \"" + getFunctionReturnName() +"\"");
357+
" add a SqlOutParameter with name '" + getFunctionReturnName() + "'");
352358
}
353359
else {
354-
setFunctionReturnName(parameter.getName());
360+
setFunctionReturnName(param.getName());
355361
}
356362
}
357363
else {
358-
parameter = declaredParameters.get(parNameToCheck);
364+
param = declaredParams.get(paramNameToCheck);
359365
}
360-
if (parameter != null) {
361-
workParameters.add(parameter);
366+
if (param != null) {
367+
workParams.add(param);
362368
if (logger.isDebugEnabled()) {
363-
logger.debug("Using declared parameter for: " +
364-
(parNameToUse == null ? getFunctionReturnName() : parNameToUse));
369+
logger.debug("Using declared parameter for '" +
370+
(paramNameToUse != null ? paramNameToUse : getFunctionReturnName()) + "'");
365371
}
366372
}
367373
}
@@ -370,57 +376,57 @@ protected List<SqlParameter> reconcileParameters(List<SqlParameter> parameters)
370376
if (!isFunction() && !isReturnValueRequired() &&
371377
this.metaDataProvider.byPassReturnParameter(meta.getParameterName())) {
372378
if (logger.isDebugEnabled()) {
373-
logger.debug("Bypassing metadata return parameter for: " + meta.getParameterName());
379+
logger.debug("Bypassing metadata return parameter for '" + meta.getParameterName() + "'");
374380
}
375381
}
376382
else {
377383
String returnNameToUse =(StringUtils.hasLength(meta.getParameterName()) ?
378-
parNameToUse : getFunctionReturnName());
379-
workParameters.add(this.metaDataProvider.createDefaultOutParameter(returnNameToUse, meta));
384+
paramNameToUse : getFunctionReturnName());
385+
workParams.add(this.metaDataProvider.createDefaultOutParameter(returnNameToUse, meta));
380386
if (isFunction()) {
381387
setFunctionReturnName(returnNameToUse);
382-
outParameterNames.add(returnNameToUse);
388+
outParamNames.add(returnNameToUse);
383389
}
384390
if (logger.isDebugEnabled()) {
385-
logger.debug("Added metadata return parameter for: " + returnNameToUse);
391+
logger.debug("Added metadata return parameter for '" + returnNameToUse + "'");
386392
}
387393
}
388394
}
389395
else {
390396
if (meta.getParameterType() == DatabaseMetaData.procedureColumnOut) {
391-
workParameters.add(this.metaDataProvider.createDefaultOutParameter(parNameToUse, meta));
392-
outParameterNames.add(parNameToUse);
397+
workParams.add(this.metaDataProvider.createDefaultOutParameter(paramNameToUse, meta));
398+
outParamNames.add(paramNameToUse);
393399
if (logger.isDebugEnabled()) {
394-
logger.debug("Added metadata out parameter for: " + parNameToUse);
400+
logger.debug("Added metadata out parameter for '" + paramNameToUse + "'");
395401
}
396402
}
397403
else if (meta.getParameterType() == DatabaseMetaData.procedureColumnInOut) {
398-
workParameters.add(this.metaDataProvider.createDefaultInOutParameter(parNameToUse, meta));
399-
outParameterNames.add(parNameToUse);
404+
workParams.add(this.metaDataProvider.createDefaultInOutParameter(paramNameToUse, meta));
405+
outParamNames.add(paramNameToUse);
400406
if (logger.isDebugEnabled()) {
401-
logger.debug("Added metadata in out parameter for: " + parNameToUse);
407+
logger.debug("Added metadata in out parameter for '" + paramNameToUse + "'");
402408
}
403409
}
404410
else {
405411
if (this.limitedInParameterNames.isEmpty() ||
406-
limitedInParamNamesMap.containsKey(parNameToUse.toLowerCase())) {
407-
workParameters.add(this.metaDataProvider.createDefaultInParameter(parNameToUse, meta));
412+
limitedInParamNamesMap.containsKey(paramNameToUse.toLowerCase())) {
413+
workParams.add(this.metaDataProvider.createDefaultInParameter(paramNameToUse, meta));
408414
if (logger.isDebugEnabled()) {
409-
logger.debug("Added metadata in parameter for: " + parNameToUse);
415+
logger.debug("Added metadata in parameter for '" + paramNameToUse + "'");
410416
}
411417
}
412418
else {
413419
if (logger.isDebugEnabled()) {
414420
logger.debug("Limited set of parameters " + limitedInParamNamesMap.keySet() +
415-
" skipped parameter for: " + parNameToUse);
421+
" skipped parameter for '" + paramNameToUse + "'");
416422
}
417423
}
418424
}
419425
}
420426
}
421427
}
422428

423-
return workParameters;
429+
return workParams;
424430
}
425431

426432
/**

0 commit comments

Comments
 (0)