[#1727] Cast VARCHAR bind values to their actual string length
This commit is contained in:
parent
a8a1b0190b
commit
b708cc15e4
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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(")");
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user