Dear jOOQ folks,
I recently realized that jOOQ does not support byte[] inside a postgresql
UDT.
This was pretty sad since I tried to use this UDT:
CREATE TYPE password_hash AS (
version smallint,
salt bytea,
hash bytea
);
When looking at FieldTypeHelper.java things became obvious ...
//
-------------------------------------------------------------------------
// The following section has been added for Postgres UDT support. The
// official Postgres JDBC driver does not implement SQLData and similar
// interfaces. Instead, a string representation of a UDT has to be
parsed
//
-------------------------------------------------------------------------
private static <T> T pgFromString(Class<? extends T> type, String
string) throws SQLException {
// ..........
else if (type == byte[].class) {
// Not supported
}
// ..........
As I would love to see full support for UDT in postgresql I attached
a patch which works for my current version 9.1. Would be cool to find it in
jOOQ soon :-))
Best regards,
Peter
Index: jOOQ/src/main/java/org/jooq/impl/FieldTypeHelper.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- jOOQ/src/main/java/org/jooq/impl/FieldTypeHelper.java (revision 2159)
+++ jOOQ/src/main/java/org/jooq/impl/FieldTypeHelper.java (revision )
@@ -40,6 +40,9 @@
import static org.jooq.SQLDialect.POSTGRES;
import static org.jooq.impl.Factory.getNewFactory;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.StringReader;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Array;
@@ -112,6 +115,8 @@
private static final int SHORT_PRECISION = String.valueOf(Short.MAX_VALUE).length();
private static final int BYTE_PRECISION = String.valueOf(Byte.MAX_VALUE).length();
+ private static final String POSTGRESQL_HEX_STRING_PREFIX = "\\\\x";
+
private static final JooqLogger log = JooqLogger.getLogger(FieldTypeHelper.class);
@SuppressWarnings("unchecked")
@@ -927,7 +932,7 @@
return (T) Byte.valueOf(string);
}
else if (type == byte[].class) {
- // Not supported
+ return (T)pgParseBytes(string);
}
else if (type == Clob.class) {
// Not supported
@@ -991,6 +996,48 @@
}
throw new UnsupportedOperationException("Class " + type + " is not supported");
+ }
+
+ private static byte[] pgParseBytes(final String string) {
+ if (string.startsWith(POSTGRESQL_HEX_STRING_PREFIX)) {
+ return hexDecode(string.substring(POSTGRESQL_HEX_STRING_PREFIX.length()));
+ }
+ throw new IllegalArgumentException("unknown postgresql string format for bytes: " + string);
+ }
+
+ private static byte[] hexDecode(final String hex) {
+ final StringReader input = new StringReader(hex);
+ final ByteArrayOutputStream bytes = new ByteArrayOutputStream(hex.length() / 2);
+ int hexDigit;
+ int byteValue;
+ try
+ {
+ while((hexDigit = input.read()) != -1) {
+ byteValue = (hexValue(hexDigit) << 4);
+ if((hexDigit = input.read()) == -1) {
+ break;
+ }
+ byteValue += hexValue(hexDigit);
+ bytes.write(byteValue);
+ }
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e); // should never happen for a string reader
+ }
+ input.close();
+
+ return bytes.toByteArray();
+ }
+
+ private static int hexValue(final int hexDigit) {
+ if (hexDigit >= '0' && hexDigit <= '9') {
+ return hexDigit - '0';
+ } else if (hexDigit >= 'a' && hexDigit <= 'f') {
+ return hexDigit - 'a' + 10;
+ } else if (hexDigit >= 'A' && hexDigit <= 'F') {
+ return hexDigit - 'A' + 10;
+ }
+ throw new IllegalArgumentException();
}
private static java.util.Date pgParseDate(String string, SimpleDateFormat f) throws SQLException {