|
|
|
@ -1,5 +1,5 @@ |
|
|
|
/* |
|
|
|
/* |
|
|
|
* Copyright 2002-2012 the original author or authors. |
|
|
|
* Copyright 2002-2013 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. |
|
|
|
@ -32,7 +32,8 @@ import org.springframework.util.Assert; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Helper methods for named parameter parsing. |
|
|
|
* Helper methods for named parameter parsing. |
|
|
|
* Only intended for internal use within Spring's JDBC framework. |
|
|
|
* |
|
|
|
|
|
|
|
* <p>Only intended for internal use within Spring's JDBC framework. |
|
|
|
* |
|
|
|
* |
|
|
|
* @author Thomas Risberg |
|
|
|
* @author Thomas Risberg |
|
|
|
* @author Juergen Hoeller |
|
|
|
* @author Juergen Hoeller |
|
|
|
@ -112,11 +113,13 @@ public abstract class NamedParameterUtils { |
|
|
|
while (j < statement.length && !('}' == statement[j])) { |
|
|
|
while (j < statement.length && !('}' == statement[j])) { |
|
|
|
j++; |
|
|
|
j++; |
|
|
|
if (':' == statement[j] || '{' == statement[j]) { |
|
|
|
if (':' == statement[j] || '{' == statement[j]) { |
|
|
|
throw new InvalidDataAccessApiUsageException("Parameter name contains invalid character '" + statement[j] + "' at position " + i + " in statement " + sql); |
|
|
|
throw new InvalidDataAccessApiUsageException("Parameter name contains invalid character '" + |
|
|
|
|
|
|
|
statement[j] + "' at position " + i + " in statement: " + sql); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if (j >= statement.length) { |
|
|
|
if (j >= statement.length) { |
|
|
|
throw new InvalidDataAccessApiUsageException("Non-terminated named parameter declaration at position " + i + " in statement " + sql); |
|
|
|
throw new InvalidDataAccessApiUsageException( |
|
|
|
|
|
|
|
"Non-terminated named parameter declaration at position " + i + " in statement: " + sql); |
|
|
|
} |
|
|
|
} |
|
|
|
if (j - i > 3) { |
|
|
|
if (j - i > 3) { |
|
|
|
parameter = sql.substring(i + 2, j); |
|
|
|
parameter = sql.substring(i + 2, j); |
|
|
|
@ -165,8 +168,9 @@ public abstract class NamedParameterUtils { |
|
|
|
return parsedSql; |
|
|
|
return parsedSql; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static int addNamedParameter(List<ParameterHolder> parameterList, int totalParameterCount, int escapes, int i, int j, |
|
|
|
private static int addNamedParameter( |
|
|
|
String parameter) { |
|
|
|
List<ParameterHolder> parameterList, int totalParameterCount, int escapes, int i, int j, String parameter) { |
|
|
|
|
|
|
|
|
|
|
|
parameterList.add(new ParameterHolder(parameter, i - escapes, j - escapes)); |
|
|
|
parameterList.add(new ParameterHolder(parameter, i - escapes, j - escapes)); |
|
|
|
totalParameterCount++; |
|
|
|
totalParameterCount++; |
|
|
|
return totalParameterCount; |
|
|
|
return totalParameterCount; |
|
|
|
@ -229,18 +233,18 @@ public abstract class NamedParameterUtils { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Parse the SQL statement and locate any placeholders or named parameters. |
|
|
|
* Parse the SQL statement and locate any placeholders or named parameters. Named |
|
|
|
* Named parameters are substituted for a JDBC placeholder and any select list |
|
|
|
* parameters are substituted for a JDBC placeholder, and any select list is expanded |
|
|
|
* is expanded to the required number of placeholders. Select lists may contain |
|
|
|
* to the required number of placeholders. Select lists may contain an array of |
|
|
|
* an array of objects and in that case the placeholders will be grouped and |
|
|
|
* objects, and in that case the placeholders will be grouped and enclosed with |
|
|
|
* enclosed with parantheses. This allows for the use of "expression lists" in |
|
|
|
* parentheses. This allows for the use of "expression lists" in the SQL statement |
|
|
|
* the SQL statement like:<br/> |
|
|
|
* like: <br /><br /> |
|
|
|
* select id, name, state from table where (name, age) in (('John', 35), ('Ann', 50)) |
|
|
|
* {@code select id, name, state from table where (name, age) in (('John', 35), ('Ann', 50))} |
|
|
|
* <p>The parameter values passed in are used to determine the number of |
|
|
|
* <p>The parameter values passed in are used to determine the number of placeholders to |
|
|
|
* placeholder to be used for a select list. Select lists should be limited |
|
|
|
* be used for a select list. Select lists should be limited to 100 or fewer elements. |
|
|
|
* to 100 or fewer elements. A larger number of elements is not guaramteed to |
|
|
|
* A larger number of elements is not guaranteed to be supported by the database and |
|
|
|
* be supported by the database and is strictly vendor-dependent. |
|
|
|
* is strictly vendor-dependent. |
|
|
|
* @param parsedSql the parsed represenation of the SQL statement |
|
|
|
* @param parsedSql the parsed representation of the SQL statement |
|
|
|
* @param paramSource the source for named parameters |
|
|
|
* @param paramSource the source for named parameters |
|
|
|
* @return the SQL statement with substituted parameters |
|
|
|
* @return the SQL statement with substituted parameters |
|
|
|
* @see #parseSqlStatement |
|
|
|
* @see #parseSqlStatement |
|
|
|
@ -255,7 +259,7 @@ public abstract class NamedParameterUtils { |
|
|
|
int[] indexes = parsedSql.getParameterIndexes(i); |
|
|
|
int[] indexes = parsedSql.getParameterIndexes(i); |
|
|
|
int startIndex = indexes[0]; |
|
|
|
int startIndex = indexes[0]; |
|
|
|
int endIndex = indexes[1]; |
|
|
|
int endIndex = indexes[1]; |
|
|
|
actualSql.append(originalSql.substring(lastIndex, startIndex)); |
|
|
|
actualSql.append(originalSql, lastIndex, startIndex); |
|
|
|
if (paramSource != null && paramSource.hasValue(paramName)) { |
|
|
|
if (paramSource != null && paramSource.hasValue(paramName)) { |
|
|
|
Object value = paramSource.getValue(paramName); |
|
|
|
Object value = paramSource.getValue(paramName); |
|
|
|
if (value instanceof SqlParameterValue) { |
|
|
|
if (value instanceof SqlParameterValue) { |
|
|
|
@ -295,7 +299,7 @@ public abstract class NamedParameterUtils { |
|
|
|
} |
|
|
|
} |
|
|
|
lastIndex = endIndex; |
|
|
|
lastIndex = endIndex; |
|
|
|
} |
|
|
|
} |
|
|
|
actualSql.append(originalSql.substring(lastIndex, originalSql.length())); |
|
|
|
actualSql.append(originalSql, lastIndex, originalSql.length()); |
|
|
|
return actualSql.toString(); |
|
|
|
return actualSql.toString(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -314,10 +318,10 @@ public abstract class NamedParameterUtils { |
|
|
|
Object[] paramArray = new Object[parsedSql.getTotalParameterCount()]; |
|
|
|
Object[] paramArray = new Object[parsedSql.getTotalParameterCount()]; |
|
|
|
if (parsedSql.getNamedParameterCount() > 0 && parsedSql.getUnnamedParameterCount() > 0) { |
|
|
|
if (parsedSql.getNamedParameterCount() > 0 && parsedSql.getUnnamedParameterCount() > 0) { |
|
|
|
throw new InvalidDataAccessApiUsageException( |
|
|
|
throw new InvalidDataAccessApiUsageException( |
|
|
|
"You can't mix named and traditional ? placeholders. You have " + |
|
|
|
"Not allowed to mix named and traditional ? placeholders. You have " + |
|
|
|
parsedSql.getNamedParameterCount() + " named parameter(s) and " + |
|
|
|
parsedSql.getNamedParameterCount() + " named parameter(s) and " + |
|
|
|
parsedSql.getUnnamedParameterCount() + " traditonal placeholder(s) in [" + |
|
|
|
parsedSql.getUnnamedParameterCount() + " traditional placeholder(s) in statement: " + |
|
|
|
parsedSql.getOriginalSql() + "]"); |
|
|
|
parsedSql.getOriginalSql()); |
|
|
|
} |
|
|
|
} |
|
|
|
List<String> paramNames = parsedSql.getParameterNames(); |
|
|
|
List<String> paramNames = parsedSql.getParameterNames(); |
|
|
|
for (int i = 0; i < paramNames.size(); i++) { |
|
|
|
for (int i = 0; i < paramNames.size(); i++) { |
|
|
|
@ -408,15 +412,12 @@ public abstract class NamedParameterUtils { |
|
|
|
List<String> paramNames = parsedSql.getParameterNames(); |
|
|
|
List<String> paramNames = parsedSql.getParameterNames(); |
|
|
|
List<SqlParameter> params = new LinkedList<SqlParameter>(); |
|
|
|
List<SqlParameter> params = new LinkedList<SqlParameter>(); |
|
|
|
for (String paramName : paramNames) { |
|
|
|
for (String paramName : paramNames) { |
|
|
|
SqlParameter param = new SqlParameter( |
|
|
|
params.add(new SqlParameter(paramName, paramSource.getSqlType(paramName), paramSource.getTypeName(paramName))); |
|
|
|
paramName, |
|
|
|
|
|
|
|
paramSource.getSqlType(paramName), |
|
|
|
|
|
|
|
paramSource.getTypeName(paramName)); |
|
|
|
|
|
|
|
params.add(param); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
return params; |
|
|
|
return params; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
// Convenience methods operating on a plain SQL String
|
|
|
|
// Convenience methods operating on a plain SQL String
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
@ -463,28 +464,32 @@ public abstract class NamedParameterUtils { |
|
|
|
return buildValueArray(parsedSql, new MapSqlParameterSource(paramMap), null); |
|
|
|
return buildValueArray(parsedSql, new MapSqlParameterSource(paramMap), null); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static class ParameterHolder { |
|
|
|
private static class ParameterHolder { |
|
|
|
private String parameterName; |
|
|
|
|
|
|
|
private int startIndex; |
|
|
|
private final String parameterName; |
|
|
|
private int endIndex; |
|
|
|
|
|
|
|
|
|
|
|
private final int startIndex; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final int endIndex; |
|
|
|
|
|
|
|
|
|
|
|
public ParameterHolder(String parameterName, int startIndex, int endIndex) { |
|
|
|
public ParameterHolder(String parameterName, int startIndex, int endIndex) { |
|
|
|
super(); |
|
|
|
|
|
|
|
this.parameterName = parameterName; |
|
|
|
this.parameterName = parameterName; |
|
|
|
this.startIndex = startIndex; |
|
|
|
this.startIndex = startIndex; |
|
|
|
this.endIndex = endIndex; |
|
|
|
this.endIndex = endIndex; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public String getParameterName() { |
|
|
|
public String getParameterName() { |
|
|
|
return parameterName; |
|
|
|
return this.parameterName; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public int getStartIndex() { |
|
|
|
public int getStartIndex() { |
|
|
|
return startIndex; |
|
|
|
return this.startIndex; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public int getEndIndex() { |
|
|
|
public int getEndIndex() { |
|
|
|
return endIndex; |
|
|
|
return this.endIndex; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|