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 {

Reply via email to