diff --git a/jOOQ-test/src/org/jooq/test/_/testcases/RenderAndBindTests.java b/jOOQ-test/src/org/jooq/test/_/testcases/RenderAndBindTests.java index 243e7c074c..c9675a19ac 100644 --- a/jOOQ-test/src/org/jooq/test/_/testcases/RenderAndBindTests.java +++ b/jOOQ-test/src/org/jooq/test/_/testcases/RenderAndBindTests.java @@ -301,7 +301,7 @@ extends BaseTest extends AbstractField implements Param, BindingProvider { * Inlining abstraction */ private void toSQL(RenderContext context, Object val, Class type) { + SQLDialect dialect = context.getDialect(); + if (context.inline()) { if (val == null) { context.sql("null"); @@ -258,7 +263,7 @@ class Val extends AbstractField implements Param, BindingProvider { // [#1153] Some dialects don't support boolean literals // TRUE and FALSE - if (asList(ASE, DB2, ORACLE, SQLSERVER, SQLITE, SYBASE).contains(context.getDialect())) { + if (asList(ASE, DB2, ORACLE, SQLSERVER, SQLITE, SYBASE).contains(dialect)) { context.sql(((Boolean) val) ? "1" : "0"); } else { @@ -266,9 +271,25 @@ class Val extends AbstractField implements Param, BindingProvider { } } else if (type == byte[].class) { - context.sql("'") - .sql(Arrays.toString((byte[]) val).replace("'", "''")) - .sql("'"); + byte[] binary = (byte[]) val; + + // [#1154] Binary data cannot always be inlined + if (dialect == H2) { + context.sql("X'") + .sql(StringUtils.convertBytesToHex(binary)) + .sql("'"); + } + else if (Util.getStatementType(context.getSettings()) == STATEMENT) { + throw new DataAccessException("Cannot inline binary data in dialect " + dialect + ". Use StatementType.PREPARED_STATEMENT instead"); + } + + // This default behaviour is used in debug logging for dialects + // that do not support inlining binary data + else { + context.sql("'") + .sql(Arrays.toString(binary).replace("'", "''")) + .sql("'"); + } } else if (Number.class.isAssignableFrom(type)) { context.sql(val.toString()); @@ -276,7 +297,7 @@ class Val extends AbstractField implements Param, BindingProvider { else if (type.isArray()) { // H2 renders arrays as tuples - if (context.getDialect() == H2) { + if (dialect == H2) { context.sql(Arrays.toString((Object[]) val).replaceAll("\\[([^]]*)\\]", "($1)")); } @@ -312,13 +333,13 @@ class Val extends AbstractField implements Param, BindingProvider { // In Postgres, some additional casting must be done in some cases... // TODO: Improve this implementation with [#215] (cast support) - else if (context.getDialect() == SQLDialect.POSTGRES) { + else if (dialect == SQLDialect.POSTGRES) { // Postgres needs explicit casting for array types if (type.isArray() && byte[].class != type) { context.sql(getBindVariable(context)); context.sql("::"); - context.sql(FieldTypeHelper.getDataType(context.getDialect(), type).getCastTypeName(context)); + context.sql(FieldTypeHelper.getDataType(dialect, type).getCastTypeName(context)); } // ... and also for enum types diff --git a/jOOQ/src/main/java/org/jooq/tools/Convert.java b/jOOQ/src/main/java/org/jooq/tools/Convert.java index 5e7473f80c..081c3ef363 100644 --- a/jOOQ/src/main/java/org/jooq/tools/Convert.java +++ b/jOOQ/src/main/java/org/jooq/tools/Convert.java @@ -223,10 +223,18 @@ public final class Convert { else { final Class fromClass = from.getClass(); + // No conversion if (toClass == fromClass) { return (T) from; } + + // [#1155] Do this early: identity-conversion into Object + else if (toClass == Object.class) { + return (T) from; + } else if (fromClass == byte[].class) { + + // This may not make much sense. Any other options? return convert(Arrays.toString((byte[]) from), toClass); } else if (fromClass.isArray()) { @@ -242,11 +250,6 @@ public final class Convert { return (T) from.toString(); } - // All types can be converted into Object - else if (toClass == Object.class) { - return (T) from; - } - // Various number types are converted between each other via String else if (toClass == Byte.class || toClass == byte.class) { return (T) Byte.valueOf(new BigDecimal(from.toString().trim()).byteValue()); diff --git a/jOOQ/src/main/java/org/jooq/tools/StringUtils.java b/jOOQ/src/main/java/org/jooq/tools/StringUtils.java index 66a6ab6339..09ee20ae0c 100644 --- a/jOOQ/src/main/java/org/jooq/tools/StringUtils.java +++ b/jOOQ/src/main/java/org/jooq/tools/StringUtils.java @@ -936,4 +936,38 @@ public final class StringUtils { String cc = toCamelCase(string); return cc.substring(0, 1).toLowerCase() + cc.substring(1); } + + // ------------------------------------------------------------------------ + // XXX This section is taken from the H2 Database + // ------------------------------------------------------------------------ + + private static final char[] HEX = "0123456789abcdef".toCharArray(); + + /** + * Convert a byte array to a hex encoded string. + * + * @param value the byte array + * @return the hex encoded string + */ + public static String convertBytesToHex(byte[] value) { + return convertBytesToHex(value, value.length); + } + + /** + * Convert a byte array to a hex encoded string. + * + * @param value the byte array + * @param len the number of bytes to encode + * @return the hex encoded string + */ + public static String convertBytesToHex(byte[] value, int len) { + char[] buff = new char[len + len]; + char[] hex = HEX; + for (int i = 0; i < len; i++) { + int c = value[i] & 0xff; + buff[i + i] = hex[c >> 4]; + buff[i + i + 1] = hex[c & 0xf]; + } + return new String(buff); + } }