Browse Source

Avoid NPE for anonymous SqlParameter in CallMetaDataContext

Issue: SPR-13628
(cherry picked from commit d1f5ee2)
pull/1057/head
Juergen Hoeller 10 years ago
parent
commit
2ea69c37c6
  1. 116
      spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallMetaDataContext.java

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

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2014 the original author or authors. * Copyright 2002-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -280,88 +280,94 @@ public class CallMetaDataContext {
* Reconcile the provided parameters with available metadata and add new ones where appropriate. * Reconcile the provided parameters with available metadata and add new ones where appropriate.
*/ */
protected List<SqlParameter> reconcileParameters(List<SqlParameter> parameters) { protected List<SqlParameter> reconcileParameters(List<SqlParameter> parameters) {
final List<SqlParameter> declaredReturnParameters = new ArrayList<SqlParameter>(); final List<SqlParameter> declaredReturnParams = new ArrayList<SqlParameter>();
final Map<String, SqlParameter> declaredParameters = new LinkedHashMap<String, SqlParameter>(); final Map<String, SqlParameter> declaredParams = new LinkedHashMap<String, SqlParameter>();
boolean returnDeclared = false; boolean returnDeclared = false;
List<String> outParameterNames = new ArrayList<String>(); List<String> outParamNames = new ArrayList<String>();
List<String> metaDataParameterNames = new ArrayList<String>(); List<String> metaDataParamNames = new ArrayList<String>();
// Get the names of the meta data parameters // Get the names of the meta data parameters
for (CallParameterMetaData meta : this.metaDataProvider.getCallParameterMetaData()) { for (CallParameterMetaData meta : this.metaDataProvider.getCallParameterMetaData()) {
if (meta.getParameterType() != DatabaseMetaData.procedureColumnReturn) { if (meta.getParameterType() != DatabaseMetaData.procedureColumnReturn) {
metaDataParameterNames.add(meta.getParameterName().toLowerCase()); metaDataParamNames.add(meta.getParameterName().toLowerCase());
} }
} }
// Separate implicit return parameters from explicit parameters... // Separate implicit return parameters from explicit parameters...
for (SqlParameter parameter : parameters) { for (SqlParameter param : parameters) {
if (parameter.isResultsParameter()) { if (param.isResultsParameter()) {
declaredReturnParameters.add(parameter); declaredReturnParams.add(param);
} }
else { else {
String parameterNameToMatch = this.metaDataProvider.parameterNameToUse(parameter.getName()).toLowerCase(); String paramName = param.getName();
declaredParameters.put(parameterNameToMatch, parameter); if (paramName == null) {
if (parameter instanceof SqlOutParameter) { throw new IllegalArgumentException("Anonymous parameters not supported for calls - " +
outParameterNames.add(parameter.getName()); "please specify a name for the parameter of SQL type " + param.getSqlType());
if (isFunction() && !metaDataParameterNames.contains(parameterNameToMatch)) { }
String paramNameToMatch = this.metaDataProvider.parameterNameToUse(paramName).toLowerCase();
declaredParams.put(paramNameToMatch, param);
if (param instanceof SqlOutParameter) {
outParamNames.add(paramName);
if (isFunction() && !metaDataParamNames.contains(paramNameToMatch)) {
if (!returnDeclared) { if (!returnDeclared) {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("Using declared out parameter '" + parameter.getName() + "' for function return value"); logger.debug("Using declared out parameter '" + paramName +
"' for function return value");
} }
setFunctionReturnName(parameter.getName()); setFunctionReturnName(paramName);
returnDeclared = true; returnDeclared = true;
} }
} }
} }
} }
} }
setOutParameterNames(outParameterNames); setOutParameterNames(outParamNames);
List<SqlParameter> workParameters = new ArrayList<SqlParameter>(); List<SqlParameter> workParams = new ArrayList<SqlParameter>();
workParameters.addAll(declaredReturnParameters); workParams.addAll(declaredReturnParams);
if (!this.metaDataProvider.isProcedureColumnMetaDataUsed()) { if (!this.metaDataProvider.isProcedureColumnMetaDataUsed()) {
workParameters.addAll(declaredParameters.values()); workParams.addAll(declaredParams.values());
return workParameters; return workParams;
} }
Map<String, String> limitedInParamNamesMap = new HashMap<String, String>(this.limitedInParameterNames.size()); Map<String, String> limitedInParamNamesMap = new HashMap<String, String>(this.limitedInParameterNames.size());
for (String limitedParameterName : this.limitedInParameterNames) { for (String limitedParamName : this.limitedInParameterNames) {
limitedInParamNamesMap.put( limitedInParamNamesMap.put(
this.metaDataProvider.parameterNameToUse(limitedParameterName).toLowerCase(), limitedParameterName); this.metaDataProvider.parameterNameToUse(limitedParamName).toLowerCase(), limitedParamName);
} }
for (CallParameterMetaData meta : this.metaDataProvider.getCallParameterMetaData()) { for (CallParameterMetaData meta : this.metaDataProvider.getCallParameterMetaData()) {
String parNameToCheck = null; String paramNameToCheck = null;
if (meta.getParameterName() != null) { if (meta.getParameterName() != null) {
parNameToCheck = this.metaDataProvider.parameterNameToUse(meta.getParameterName()).toLowerCase(); paramNameToCheck = this.metaDataProvider.parameterNameToUse(meta.getParameterName()).toLowerCase();
} }
String parNameToUse = this.metaDataProvider.parameterNameToUse(meta.getParameterName()); String paramNameToUse = this.metaDataProvider.parameterNameToUse(meta.getParameterName());
if (declaredParameters.containsKey(parNameToCheck) || if (declaredParams.containsKey(paramNameToCheck) ||
(meta.getParameterType() == DatabaseMetaData.procedureColumnReturn && returnDeclared)) { (meta.getParameterType() == DatabaseMetaData.procedureColumnReturn && returnDeclared)) {
SqlParameter parameter; SqlParameter param;
if (meta.getParameterType() == DatabaseMetaData.procedureColumnReturn) { if (meta.getParameterType() == DatabaseMetaData.procedureColumnReturn) {
parameter = declaredParameters.get(getFunctionReturnName()); param = declaredParams.get(getFunctionReturnName());
if (parameter == null && getOutParameterNames().size() > 0) { if (param == null && getOutParameterNames().size() > 0) {
parameter = declaredParameters.get(getOutParameterNames().get(0).toLowerCase()); param = declaredParams.get(getOutParameterNames().get(0).toLowerCase());
} }
if (parameter == null) { if (param == null) {
throw new InvalidDataAccessApiUsageException( throw new InvalidDataAccessApiUsageException(
"Unable to locate declared parameter for function return value - " + "Unable to locate declared parameter for function return value - " +
" add a SqlOutParameter with name \"" + getFunctionReturnName() +"\""); " add a SqlOutParameter with name '" + getFunctionReturnName() + "'");
} }
else { else {
setFunctionReturnName(parameter.getName()); setFunctionReturnName(param.getName());
} }
} }
else { else {
parameter = declaredParameters.get(parNameToCheck); param = declaredParams.get(paramNameToCheck);
} }
if (parameter != null) { if (param != null) {
workParameters.add(parameter); workParams.add(param);
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("Using declared parameter for: " + logger.debug("Using declared parameter for '" +
(parNameToUse == null ? getFunctionReturnName() : parNameToUse)); (paramNameToUse != null ? paramNameToUse : getFunctionReturnName()) + "'");
} }
} }
} }
@ -370,49 +376,49 @@ public class CallMetaDataContext {
if (!isFunction() && !isReturnValueRequired() && if (!isFunction() && !isReturnValueRequired() &&
this.metaDataProvider.byPassReturnParameter(meta.getParameterName())) { this.metaDataProvider.byPassReturnParameter(meta.getParameterName())) {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("Bypassing metadata return parameter for: " + meta.getParameterName()); logger.debug("Bypassing metadata return parameter for '" + meta.getParameterName() + "'");
} }
} }
else { else {
String returnNameToUse =(StringUtils.hasLength(meta.getParameterName()) ? String returnNameToUse =(StringUtils.hasLength(meta.getParameterName()) ?
parNameToUse : getFunctionReturnName()); paramNameToUse : getFunctionReturnName());
workParameters.add(this.metaDataProvider.createDefaultOutParameter(returnNameToUse, meta)); workParams.add(this.metaDataProvider.createDefaultOutParameter(returnNameToUse, meta));
if (isFunction()) { if (isFunction()) {
setFunctionReturnName(returnNameToUse); setFunctionReturnName(returnNameToUse);
outParameterNames.add(returnNameToUse); outParamNames.add(returnNameToUse);
} }
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("Added metadata return parameter for: " + returnNameToUse); logger.debug("Added metadata return parameter for '" + returnNameToUse + "'");
} }
} }
} }
else { else {
if (meta.getParameterType() == DatabaseMetaData.procedureColumnOut) { if (meta.getParameterType() == DatabaseMetaData.procedureColumnOut) {
workParameters.add(this.metaDataProvider.createDefaultOutParameter(parNameToUse, meta)); workParams.add(this.metaDataProvider.createDefaultOutParameter(paramNameToUse, meta));
outParameterNames.add(parNameToUse); outParamNames.add(paramNameToUse);
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("Added metadata out parameter for: " + parNameToUse); logger.debug("Added metadata out parameter for '" + paramNameToUse + "'");
} }
} }
else if (meta.getParameterType() == DatabaseMetaData.procedureColumnInOut) { else if (meta.getParameterType() == DatabaseMetaData.procedureColumnInOut) {
workParameters.add(this.metaDataProvider.createDefaultInOutParameter(parNameToUse, meta)); workParams.add(this.metaDataProvider.createDefaultInOutParameter(paramNameToUse, meta));
outParameterNames.add(parNameToUse); outParamNames.add(paramNameToUse);
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("Added metadata in out parameter for: " + parNameToUse); logger.debug("Added metadata in out parameter for '" + paramNameToUse + "'");
} }
} }
else { else {
if (this.limitedInParameterNames.isEmpty() || if (this.limitedInParameterNames.isEmpty() ||
limitedInParamNamesMap.containsKey(parNameToUse.toLowerCase())) { limitedInParamNamesMap.containsKey(paramNameToUse.toLowerCase())) {
workParameters.add(this.metaDataProvider.createDefaultInParameter(parNameToUse, meta)); workParams.add(this.metaDataProvider.createDefaultInParameter(paramNameToUse, meta));
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("Added metadata in parameter for: " + parNameToUse); logger.debug("Added metadata in parameter for '" + paramNameToUse + "'");
} }
} }
else { else {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("Limited set of parameters " + limitedInParamNamesMap.keySet() + logger.debug("Limited set of parameters " + limitedInParamNamesMap.keySet() +
" skipped parameter for: " + parNameToUse); " skipped parameter for '" + paramNameToUse + "'");
} }
} }
} }
@ -420,7 +426,7 @@ public class CallMetaDataContext {
} }
} }
return workParameters; return workParams;
} }
/** /**

Loading…
Cancel
Save