changeset 894:07a4998898a8

Improve and optimize PreparedStatement.setBigDecimal() implementation. It now checks on null input parameter to prevent NPE. Also removed code to trim leading zero's. Extended BugDecimalRound_Bug_3561() test with more values, including a null input parameter.
author Martin van Dinther <martin.van.dinther@monetdbsolutions.com>
date Thu, 18 Apr 2024 14:37:01 +0200 (11 months ago)
parents 3b215a009634
children 7a8f6d3d6680
files src/main/java/org/monetdb/jdbc/MonetPreparedStatement.java tests/JDBC_API_Tester.java
diffstat 2 files changed, 51 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- a/src/main/java/org/monetdb/jdbc/MonetPreparedStatement.java
+++ b/src/main/java/org/monetdb/jdbc/MonetPreparedStatement.java
@@ -564,29 +564,24 @@ public class MonetPreparedStatement
 	 * @throws SQLException if a database access error occurs
 	 */
 	@Override
-	public void setBigDecimal(final int parameterIndex, BigDecimal x) throws SQLException {
-		// get array position
-		final int i = getParamIdx(parameterIndex);
-
-		// round to the scale of the DB:
-		x = x.setScale(scale[i], java.math.RoundingMode.HALF_UP);
-
-		// if precision is now greater than that of the db, throw an error:
-		if (x.precision() > digits[i]) {
-			throw new SQLDataException("DECIMAL value exceeds allowed digits/scale: " + x.toPlainString() + " (" + digits[i] + "/" + scale[i] + ")", "22003");
+	public void setBigDecimal(final int parameterIndex, final BigDecimal x) throws SQLException
+	{
+		if (x == null) {
+			setValue(parameterIndex, "NULL");
+			return;
 		}
 
-		// MonetDB doesn't like leading 0's, since it counts them as part of
-		// the precision, so let's strip them off. (But be careful not to do
-		// this to the exact number "0".)  Also strip off trailing
-		// numbers that are inherent to the double representation.
-		String xStr = x.toPlainString();
-		final int dot = xStr.indexOf('.');
-		if (dot >= 0)
-			xStr = xStr.substring(0, Math.min(xStr.length(), dot + 1 + scale[i]));
-		while (xStr.startsWith("0") && xStr.length() > 1)
-			xStr = xStr.substring(1);
-		setValue(parameterIndex, xStr);
+		// get array position
+		final int i = getParamIdx(parameterIndex);
+		// round to the scale of the DB specification:
+		final BigDecimal decval = x.setScale(scale[i], java.math.RoundingMode.HALF_UP);
+		final String decvalStr = decval.toPlainString();
+
+		// if precision is now greater than that of the DB specification, throw an error:
+		if (decval.precision() > digits[i]) {
+			throw new SQLDataException("DECIMAL value '" + decvalStr + "' exceeds allowed digits,scale: (" + digits[i] + "," + scale[i] + ")", "22003");
+		}
+		setValue(parameterIndex, decvalStr);
 	}
 
 	/**
--- a/tests/JDBC_API_Tester.java
+++ b/tests/JDBC_API_Tester.java
@@ -5586,7 +5586,7 @@ final public class JDBC_API_Tester {
 		ResultSet rs = null;
 		try {
 			stmt1 = con.createStatement();
-			stmt1.executeUpdate("CREATE TABLE bug3561 (d decimal(14,4))");
+			stmt1.executeUpdate("CREATE TABLE bug3561 (d decimal(7,4))");
 
 			pst = con.prepareStatement("INSERT INTO bug3561 VALUES (?)");
 			pst.setBigDecimal(1, new BigDecimal("112.125"));
@@ -5595,6 +5595,29 @@ final public class JDBC_API_Tester {
 			pst.executeUpdate();
 			pst.setBigDecimal(1, new BigDecimal("0.012345"));
 			pst.executeUpdate();
+			pst.setBigDecimal(1, new BigDecimal(0.0/10000000));	// 0.0000
+			pst.executeUpdate();
+			pst.setBigDecimal(1, new BigDecimal(2.0/3));	// 0.666666667
+			pst.executeUpdate();
+			pst.setBigDecimal(1, new BigDecimal(11.0/7));	// 1.571428571
+			pst.executeUpdate();
+			// repeat for negative values
+			pst.setBigDecimal(1, new BigDecimal("-0112.125"));
+			pst.executeUpdate();
+			pst.setBigDecimal(1, new BigDecimal("-0212.12345"));
+			pst.executeUpdate();
+			pst.setBigDecimal(1, new BigDecimal("-0.012345"));
+			pst.executeUpdate();
+			pst.setBigDecimal(1, new BigDecimal(0.0/-10000000));	// 0.0000
+			pst.executeUpdate();
+			pst.setBigDecimal(1, new BigDecimal(-2.0/3));	// -0.666666667
+			pst.executeUpdate();
+			pst.setBigDecimal(1, new BigDecimal(-11.0/7));	// -1.571428571
+			pst.executeUpdate();
+			// check what happens if null is used
+			pst.setBigDecimal(1, null);
+			pst.executeUpdate();
+
 			pst.close();
 
 			stmt2 = con.createStatement();
@@ -5618,7 +5641,17 @@ final public class JDBC_API_Tester {
 		compareExpectedOutput("BugDecimalRound_Bug_3561",
 				"112.1250\n" +
 				"212.1235\n" +
-				"0.0123\n");
+				"0.0123\n" +
+				"0.0000\n" +
+				"0.6667\n" +
+				"1.5714\n" +
+				"-112.1250\n" +
+				"-212.1235\n" +
+				"-0.0123\n" +
+				"0.0000\n" +
+				"-0.6667\n" +
+				"-1.5714\n" +
+				"null\n");
 	}
 
 	private void BugExecuteUpdate_Bug_3350() {