Skip to content

Commit

Permalink
fix: numeric binary decode for even 10 thousands (#2327)
Browse files Browse the repository at this point in the history
* fix: numeric binary decode for even 10 thousands

binary numeric values which represented integers multiples of 10,000
from 10,000-9,990,000 were not decoded correctly

fixes #2326

* fix: numeric binary decode for even 10 thousands

more test values

* fix: numeric binary decode for even 10 thousands
  • Loading branch information
bokken committed Oct 28, 2021
1 parent 6711302 commit b3050e6
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 3 deletions.
3 changes: 3 additions & 0 deletions pgjdbc/src/main/java/org/postgresql/util/ByteConverter.java
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,9 @@ public static Number numeric(byte [] bytes, int pos, int numBytes) {
if (unscaledBI == null) {
unscaledBI = BigInteger.valueOf(unscaledInt);
}
if (effectiveWeight > 0) {
unscaledBI = unscaledBI.multiply(tenPower(effectiveWeight * 4));
}
if (effectiveScale > 0) {
unscaledBI = unscaledBI.multiply(tenPower(effectiveScale));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@
BitFieldTest.class,
BlobTest.class,
BlobTransactionTest.class,
ByteBufferByteStreamWriterTest.class,
ByteStreamWriterTest.class,
CallableStmtTest.class,
ClientEncodingTest.class,
ColumnSanitiserDisabledTest.class,
Expand All @@ -81,6 +83,7 @@
DriverTest.class,
EncodingTest.class,
ExpressionPropertiesTest.class,
FixedLengthOutputStreamTest.class,
GeometricTest.class,
GetXXXTest.class,
HostSpecTest.class,
Expand All @@ -93,14 +96,13 @@
MiscTest.class,
NativeQueryBindLengthTest.class,
NoColumnMetadataIssue1613Test.class,
NumericTransferTest.class,
NumericTransferTest2.class,
NotifyTest.class,
OidToStringTest.class,
OidValueOfTest.class,
OptionsPropertyTest.class,
OuterJoinSyntaxTest.class,
FixedLengthOutputStreamTest.class,
ByteStreamWriterTest.class,
ByteBufferByteStreamWriterTest.class,
ParameterStatusTest.class,
ParserTest.class,
PGbyteaTest.class,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
* Copyright (c) 2020, PostgreSQL Global Development Group
* See the LICENSE file in the project root for more information.
*/

package org.postgresql.test.jdbc2;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import org.postgresql.PGProperty;
import org.postgresql.core.Oid;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Properties;

@RunWith(Parameterized.class)
public class NumericTransferTest2 extends BaseTest4 {

final BigDecimal value;

public NumericTransferTest2(BinaryMode binaryMode, BigDecimal value) {
setBinaryMode(binaryMode);
this.value = value;
}

@Override
protected void updateProperties(Properties props) {
super.updateProperties(props);
PGProperty.BINARY_TRANSFER_ENABLE.set(props, Oid.NUMERIC);
}

@Parameterized.Parameters(name = "binary = {0}, value = {1,number,#,###.##################################################}")
public static Iterable<Object[]> data() {
Collection<Object[]> numbers = new ArrayList<Object[]>();
for (BinaryMode binaryMode : BinaryMode.values()) {
numbers.add(new Object[] {binaryMode, new BigDecimal("1.0")});
numbers.add(new Object[] {binaryMode, new BigDecimal("0.000000000000000000000000000000000000000000000000000")});
numbers.add(new Object[] {binaryMode, new BigDecimal("0.100000000000000000000000000000000000000000000009900")});
numbers.add(new Object[] {binaryMode, new BigDecimal("-1.0")});
numbers.add(new Object[] {binaryMode, new BigDecimal("-1")});
numbers.add(new Object[] {binaryMode, new BigDecimal("1.2")});
numbers.add(new Object[] {binaryMode, new BigDecimal("-2.05")});
numbers.add(new Object[] {binaryMode, new BigDecimal("0.000000000000000000000000000990")});
numbers.add(new Object[] {binaryMode, new BigDecimal("-0.000000000000000000000000000990")});
numbers.add(new Object[] {binaryMode, new BigDecimal("10.0000000000099")});
numbers.add(new Object[] {binaryMode, new BigDecimal(".10000000000000")});
numbers.add(new Object[] {binaryMode, new BigDecimal("1.10000000000000")});
numbers.add(new Object[] {binaryMode, new BigDecimal("99999.2")});
numbers.add(new Object[] {binaryMode, new BigDecimal("99999")});
numbers.add(new Object[] {binaryMode, new BigDecimal("-99999.2")});
numbers.add(new Object[] {binaryMode, new BigDecimal("-99999")});
numbers.add(new Object[] {binaryMode, new BigDecimal("2147483647")});
numbers.add(new Object[] {binaryMode, new BigDecimal("-2147483648")});
numbers.add(new Object[] {binaryMode, new BigDecimal("2147483648")});
numbers.add(new Object[] {binaryMode, new BigDecimal("-2147483649")});
numbers.add(new Object[] {binaryMode, new BigDecimal("9223372036854775807")});
numbers.add(new Object[] {binaryMode, new BigDecimal("-9223372036854775808")});
numbers.add(new Object[] {binaryMode, new BigDecimal("9223372036854775808")});
numbers.add(new Object[] {binaryMode, new BigDecimal("-9223372036854775809")});
numbers.add(new Object[] {binaryMode, new BigDecimal("10223372036850000000")});
numbers.add(new Object[] {binaryMode, new BigDecimal("19223372036854775807")});
numbers.add(new Object[] {binaryMode, new BigDecimal("19223372036854775807.300")});
numbers.add(new Object[] {binaryMode, new BigDecimal("-19223372036854775807.300")});
numbers.add(new Object[] {binaryMode, new BigDecimal(BigInteger.valueOf(1234567890987654321L), -1)});
numbers.add(new Object[] {binaryMode, new BigDecimal(BigInteger.valueOf(1234567890987654321L), -5)});
numbers.add(new Object[] {binaryMode, new BigDecimal(BigInteger.valueOf(-1234567890987654321L), -3)});
numbers.add(new Object[] {binaryMode, new BigDecimal(BigInteger.valueOf(6), -8)});
numbers.add(new Object[] {binaryMode, new BigDecimal("30000")});
numbers.add(new Object[] {binaryMode, new BigDecimal("40000").setScale(15)});
numbers.add(new Object[] {binaryMode, new BigDecimal("20000.00000000000000000000")});
numbers.add(new Object[] {binaryMode, new BigDecimal("9990000").setScale(10)});
numbers.add(new Object[] {binaryMode, new BigDecimal("1000000").setScale(20)});
numbers.add(new Object[] {binaryMode, new BigDecimal("10000000000000000000000000000000000000").setScale(20)});
numbers.add(new Object[] {binaryMode, new BigDecimal("90000000000000000000000000000000000000")});
}
return numbers;
}

@Test
public void receiveValue() throws SQLException {
final String valString = value.toPlainString();
try (Statement statement = con.createStatement()) {
final String sql = "SELECT " + valString + "::numeric";
try (ResultSet rs = statement.executeQuery(sql)) {
assertTrue(rs.next());
assertEquals("getBigDecimal for " + sql, valString, rs.getBigDecimal(1).toPlainString());
}
}
}

@Test
public void sendReceiveValue() throws SQLException {
final String valString = value.toPlainString();
try (PreparedStatement statement = con.prepareStatement("select ?::numeric")) {
statement.setBigDecimal(1, value);
try (ResultSet rs = statement.executeQuery()) {
rs.next();
assertEquals("getBigDecimal for " + valString, valString, rs.getBigDecimal(1).toPlainString());
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,13 @@ public static Iterable<Object[]> data() {
numbers.add(new Object[] {new BigDecimal(BigInteger.valueOf(1234567890987654321L), -5)});
numbers.add(new Object[] {new BigDecimal(BigInteger.valueOf(-1234567890987654321L), -3)});
numbers.add(new Object[] {new BigDecimal(BigInteger.valueOf(6), -8)});
numbers.add(new Object[] {new BigDecimal("30000")});
numbers.add(new Object[] {new BigDecimal("40000").setScale(15)});
numbers.add(new Object[] {new BigDecimal("20000.000000000000000000")});
numbers.add(new Object[] {new BigDecimal("9990000").setScale(8)});
numbers.add(new Object[] {new BigDecimal("1000000").setScale(31)});
numbers.add(new Object[] {new BigDecimal("10000000000000000000000000000000000000").setScale(14)});
numbers.add(new Object[] {new BigDecimal("90000000000000000000000000000000000000")});
return numbers;
}

Expand Down

0 comments on commit b3050e6

Please sign in to comment.