[#1727] Cast VARCHAR bind values to their actual string length

This commit is contained in:
Lukas Eder 2012-08-22 18:59:22 +02:00
parent a8a1b0190b
commit b708cc15e4
3 changed files with 43 additions and 3 deletions

View File

@ -139,6 +139,16 @@ public interface DataType<T> extends Serializable {
*/
String getCastTypeName(Configuration configuration);
/**
* Retrieve the dialect-specific type name associated with this data type
* used for casting
* <p>
* This is useful for some dialects that have specialised type names for
* cast expressions. Other dialects require type-length binding when
* casting, (e.g. VARCHAR(20))
*/
String getCastTypeName(Configuration configuration, int length);
/**
* Retrieve the dialect-specific type name associated with this data type
* used for casting

View File

@ -320,6 +320,20 @@ public abstract class AbstractDataType<T> implements DataType<T> {
return castTypeName;
}
@Override
public /* final */ String getCastTypeName(Configuration configuration, int length) {
String result = getCastTypeName(configuration);
if (length != 0) {
// Remove existing length information, first
result = result.replaceAll("\\([^\\)]*\\)", "");
result += "(" + length + ")";
}
return result;
}
@Override
public /* final */ String getCastTypeName(Configuration configuration, int precision, int scale) {
String result = getCastTypeName(configuration);

View File

@ -233,16 +233,32 @@ class Val<T> extends AbstractField<T> implements Param<T> {
toSQL(context, getValue(), getType());
}
// [#1727] VARCHAR types should be cast to their actual lengths
else if (getValue() != null && type == SQLDataType.VARCHAR) {
// Multiply by 4 to be sure that even UTF-32 collations will fit
// But don't use larger numbers than Derby's upper limit 32672
toSQLCast(context, getDataType(context), Math.min(32672, 4 * ((String) getValue()).length()));
}
// In all other cases, the bind variable can be cast normally
else {
toSQLCast(context, getDataType(context), 0, 0);
}
}
private void toSQLCast(RenderContext context, DataType<?> type, int precision, int scale) {
context.sql("cast(");
private void toSQLCast(RenderContext context, DataType<?> type, int length) {
context.keyword("cast(");
toSQL(context, getValue(), getType());
context.sql(" as ")
context.keyword(" as ")
.sql(type.getCastTypeName(context, length))
.sql(")");
}
private void toSQLCast(RenderContext context, DataType<?> type, int precision, int scale) {
context.keyword("cast(");
toSQL(context, getValue(), getType());
context.keyword(" as ")
.sql(type.getCastTypeName(context, precision, scale))
.sql(")");
}