diff --git a/pgjdbc/src/main/java/org/postgresql/jdbc/PgArray.java b/pgjdbc/src/main/java/org/postgresql/jdbc/PgArray.java index b8b256a17e..9635918d67 100644 --- a/pgjdbc/src/main/java/org/postgresql/jdbc/PgArray.java +++ b/pgjdbc/src/main/java/org/postgresql/jdbc/PgArray.java @@ -243,6 +243,9 @@ private int storeValues(final Object[] arr, int elementOid, final int[] dims, in case Oid.FLOAT8: arr[i] = ByteConverter.float8(fieldBytes, pos); break; + case Oid.NUMERIC: + arr[i] = ByteConverter.numeric(fieldBytes, pos, len); + break; case Oid.TEXT: case Oid.VARCHAR: Encoding encoding = connection.getEncoding(); @@ -389,6 +392,8 @@ private Class elementOidToClass(int oid) throws SQLException { return Float.class; case Oid.FLOAT8: return Double.class; + case Oid.NUMERIC: + return BigDecimal.class; case Oid.TEXT: case Oid.VARCHAR: return String.class; diff --git a/pgjdbc/src/main/java/org/postgresql/util/ByteConverter.java b/pgjdbc/src/main/java/org/postgresql/util/ByteConverter.java index 75ed5a34a1..89552b55c3 100644 --- a/pgjdbc/src/main/java/org/postgresql/util/ByteConverter.java +++ b/pgjdbc/src/main/java/org/postgresql/util/ByteConverter.java @@ -136,20 +136,28 @@ private static String numberBytesToString(short[] digits, int scale, int weight, return new String(buffer.array(), 0, buffer.position() - extra); } + public static Number numeric(byte [] bytes) { + return numeric(bytes, 0, bytes.length); + } + /** * Convert a variable length array of bytes to an integer * @param bytes array of bytes that can be decoded as an integer * @return integer */ - public static Number numeric(byte []bytes) { - if (bytes.length < 8) { + public static Number numeric(byte [] bytes, int pos, int numBytes) { + if (numBytes < 8) { throw new IllegalArgumentException("number of bytes should be at-least 8"); } - short len = ByteConverter.int2(bytes, 0); - short weight = ByteConverter.int2(bytes, 2); - short sign = ByteConverter.int2(bytes, 4); - short scale = ByteConverter.int2(bytes, 6); + short len = ByteConverter.int2(bytes, pos); + short weight = ByteConverter.int2(bytes, pos + 2); + short sign = ByteConverter.int2(bytes, pos + 4); + short scale = ByteConverter.int2(bytes, pos + 6); + + if (numBytes != (len * Short.BYTES) + 8) { + throw new IllegalArgumentException("invalid length of bytes \"numeric\" value"); + } if (!(sign == NUMERIC_POS || sign == NUMERIC_NEG @@ -166,7 +174,7 @@ public static Number numeric(byte []bytes) { } short[] digits = new short[len]; - int idx = 8; + int idx = pos + 8; for (int i = 0; i < len; i++) { short d = ByteConverter.int2(bytes, idx); idx += 2; diff --git a/pgjdbc/src/test/java/org/postgresql/test/jdbc2/PreparedStatementTest.java b/pgjdbc/src/test/java/org/postgresql/test/jdbc2/PreparedStatementTest.java index 50fa6af078..2ac51e7c34 100644 --- a/pgjdbc/src/test/java/org/postgresql/test/jdbc2/PreparedStatementTest.java +++ b/pgjdbc/src/test/java/org/postgresql/test/jdbc2/PreparedStatementTest.java @@ -519,7 +519,7 @@ public void testDoubleQuestionMark() throws SQLException { @Test public void testNumeric() throws SQLException { PreparedStatement pstmt = con.prepareStatement( - "CREATE TEMP TABLE numeric_tab (max_numeric_positive numeric, min_numeric_positive numeric, max_numeric_negative numeric, min_numeric_negative numeric, null_value numeric)"); + "CREATE TEMP TABLE numeric_tab (max_numeric_positive numeric, min_numeric_positive numeric, max_numeric_negative numeric, min_numeric_negative numeric, null_value numeric)"); pstmt.executeUpdate(); pstmt.close(); @@ -542,8 +542,8 @@ public void testNumeric() throws SQLException { values[3] = new BigDecimal("-" + minValueString); pstmt = con.prepareStatement("insert into numeric_tab values (?,?,?,?,?)"); - for(int i = 1; i < 5 ; i++) { - pstmt.setBigDecimal(i, values[i-1]); + for (int i = 1; i < 5 ; i++) { + pstmt.setBigDecimal(i, values[i - 1]); } pstmt.setNull(5, Types.NUMERIC); @@ -553,7 +553,7 @@ public void testNumeric() throws SQLException { pstmt = con.prepareStatement("select * from numeric_tab"); ResultSet rs = pstmt.executeQuery(); assertTrue(rs.next()); - for(int i = 1; i < 5 ; i++) { + for (int i = 1; i < 5 ; i++) { assertTrue(rs.getBigDecimal(i).compareTo(values[i - 1]) == 0); } rs.getDouble(5);