Skip to content

Commit

Permalink
Fix Oid.NUMERIC_ARRAY binary format
Browse files Browse the repository at this point in the history
  • Loading branch information
mahmoudbahaa committed Dec 5, 2019
1 parent 09e0ee8 commit 8306d82
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 11 deletions.
5 changes: 5 additions & 0 deletions pgjdbc/src/main/java/org/postgresql/jdbc/PgArray.java
Expand Up @@ -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();
Expand Down Expand Up @@ -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;
Expand Down
22 changes: 15 additions & 7 deletions pgjdbc/src/main/java/org/postgresql/util/ByteConverter.java
Expand Up @@ -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
Expand All @@ -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;
Expand Down
Expand Up @@ -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();

Expand All @@ -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);
Expand All @@ -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);
Expand Down

0 comments on commit 8306d82

Please sign in to comment.