[#1154] Bad inlining of byte[] in most dialects

This commit is contained in:
Lukas Eder 2012-02-16 23:50:42 +00:00
parent 0071b65f4b
commit 30f44b809a
4 changed files with 76 additions and 47 deletions

View File

@ -313,17 +313,14 @@ extends BaseTest<A, B, S, B2S, BS, L, X, D, T, U, I, IPK, T658, T725, T639, T785
Object[] array1 = create.select(vals(s1, s2, s3, s4)).fetchOneArray();
Object[] array2 = create.select(vals(b1, b2, sh1, sh2, i1, i2, l1, l2, bi1, bi2, bd1, bd2, db1, db2, f1, f2)).fetchOneArray();
Object[] array3 = create.select(vals(d1, d2, t1, t2, ts1, ts2)).fetchOneArray();
Object[] array4 = create.select(vals(by1, by2, bool1, bool2, bool3)).fetchOneArray();
assertEquals(4, array1.length);
assertEquals(16, array2.length);
assertEquals(6, array3.length);
assertEquals(5, array4.length);
assertEquals(asList(s1, s2, s3, s4), asList(array1));
assertEquals(asList((Number) b1, b2, sh1, sh2, i1, i2, l1, l2, bi1, bi2, bd1, bd2, db1, db2, f1, f2), asList(array2));
assertEquals(asList(d1, d2, t1, t2, ts1, ts2), asList(array3));
array4[0] = new String((byte[]) array4[0]);
assertEquals(asList(new String(by1), by2, bool1, bool2, bool3), asList(array4));

View File

@ -35,7 +35,9 @@
*/
package org.jooq.impl;
import static java.lang.Integer.toOctalString;
import static org.jooq.impl.Factory.getDataType;
import static org.jooq.tools.StringUtils.leftPad;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
@ -840,4 +842,53 @@ final class Util {
return StatementType.PREPARED_STATEMENT;
}
// ------------------------------------------------------------------------
// 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
*/
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
*/
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);
}
/**
* Postgres uses octals instead of hex encoding
*/
static String convertBytesToPostgresOctal(byte[] binary) {
StringBuilder sb = new StringBuilder();
for (byte b : binary) {
sb.append("\\\\");
sb.append(leftPad(toOctalString(b), 3, '0'));
}
return sb.toString();
}
}

View File

@ -42,12 +42,12 @@ import static org.jooq.SQLDialect.DERBY;
import static org.jooq.SQLDialect.H2;
import static org.jooq.SQLDialect.HSQLDB;
import static org.jooq.SQLDialect.INGRES;
import static org.jooq.SQLDialect.MYSQL;
import static org.jooq.SQLDialect.ORACLE;
import static org.jooq.SQLDialect.POSTGRES;
import static org.jooq.SQLDialect.SQLITE;
import static org.jooq.SQLDialect.SQLSERVER;
import static org.jooq.SQLDialect.SYBASE;
import static org.jooq.conf.StatementType.STATEMENT;
import java.math.BigDecimal;
import java.util.Arrays;
@ -64,8 +64,6 @@ import org.jooq.Param;
import org.jooq.RenderContext;
import org.jooq.SQLDialect;
import org.jooq.UDTRecord;
import org.jooq.exception.DataAccessException;
import org.jooq.tools.JooqLogger;
import org.jooq.tools.StringUtils;
/**
@ -270,24 +268,41 @@ class Val<T> extends AbstractField<T> implements Param<T>, BindingProvider {
context.sql(val.toString());
}
}
// [#1154] Binary data cannot always be inlined
else if (type == byte[].class) {
byte[] binary = (byte[]) val;
// [#1154] Binary data cannot always be inlined
if (dialect == H2) {
if (asList(ASE, SQLSERVER, SYBASE).contains(dialect)) {
context.sql("0x")
.sql(Util.convertBytesToHex(binary));
}
else if (dialect == DB2) {
context.sql("blob(X'")
.sql(Util.convertBytesToHex(binary))
.sql("')");
}
else if (asList(DERBY, H2, HSQLDB, INGRES, MYSQL, SQLITE).contains(dialect)) {
context.sql("X'")
.sql(StringUtils.convertBytesToHex(binary))
.sql(Util.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");
else if (asList(ORACLE).contains(dialect)) {
context.sql("hextoraw('")
.sql(Util.convertBytesToHex(binary))
.sql("')");
}
else if (dialect == POSTGRES) {
context.sql("E'")
.sql(Util.convertBytesToPostgresOctal(binary))
.sql("'::bytea");
}
// 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("'", "''"))
context.sql("X'")
.sql(Util.convertBytesToHex(binary))
.sql("'");
}
}

View File

@ -936,38 +936,4 @@ 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);
}
}