From b708cc15e4238ddcc551dc9c20c63b7a99a7a539 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Wed, 22 Aug 2012 18:59:22 +0200 Subject: [PATCH] [#1727] Cast VARCHAR bind values to their actual string length --- jOOQ/src/main/java/org/jooq/DataType.java | 10 +++++++++ .../java/org/jooq/impl/AbstractDataType.java | 14 ++++++++++++ jOOQ/src/main/java/org/jooq/impl/Val.java | 22 ++++++++++++++++--- 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/DataType.java b/jOOQ/src/main/java/org/jooq/DataType.java index ec419a2369..ec415f8070 100644 --- a/jOOQ/src/main/java/org/jooq/DataType.java +++ b/jOOQ/src/main/java/org/jooq/DataType.java @@ -139,6 +139,16 @@ public interface DataType extends Serializable { */ String getCastTypeName(Configuration configuration); + /** + * Retrieve the dialect-specific type name associated with this data type + * used for casting + *

+ * 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 diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractDataType.java b/jOOQ/src/main/java/org/jooq/impl/AbstractDataType.java index e7e9cb52e8..37ab04a1ea 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractDataType.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractDataType.java @@ -320,6 +320,20 @@ public abstract class AbstractDataType implements DataType { 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); diff --git a/jOOQ/src/main/java/org/jooq/impl/Val.java b/jOOQ/src/main/java/org/jooq/impl/Val.java index 30927b3752..eca510e127 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Val.java +++ b/jOOQ/src/main/java/org/jooq/impl/Val.java @@ -233,16 +233,32 @@ class Val extends AbstractField implements Param { 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(")"); }