Skip to content

Commit

Permalink
Allow old BigDecimal behavior via connection prop (#2248)
Browse files Browse the repository at this point in the history
* Ini

* More

* tests

* ds stuff

* Junit was added to pom for some reason

* Resolve build fails

* A change

* SQLServerResource

* RequestBoundaryMethodsTest

* Why is fx failing?

* Fix pom

* Fix pom again

* Fix pom some more

* Ok

* Rename + fixes

* whoops

* one more thing

* wth keep messing this up
  • Loading branch information
Jeffery-Wasty committed Nov 15, 2023
1 parent c64d649 commit 1f69f48
Show file tree
Hide file tree
Showing 11 changed files with 365 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -481,4 +481,20 @@ CallableStatement prepareCall(String sql, int nType, int nConcur, int nHold,
* @param accessTokenCallbackClass
*/
void setAccessTokenCallbackClass(String accessTokenCallbackClass);

/**
* Returns the current flag for calcBigDecimalScale.
*
* @return calcBigDecimalScale
* Whether calculating big decimal scale from input values is enabled.
*/
boolean getCalcBigDecimalScale();

/**
* Specifies whether to calculate scale from inputted big decimal values.
*
* @param calcBigDecimalScale
* A boolean that indicates if the driver should calculate scale from inputted big decimal values.
*/
void setCalcBigDecimalScale(boolean computeBigDecimal);
}
Original file line number Diff line number Diff line change
Expand Up @@ -1313,4 +1313,19 @@ public interface ISQLServerDataSource extends javax.sql.CommonDataSource {
* @param accessTokenCallbackClass
*/
void setAccessTokenCallbackClass(String accessTokenCallbackClass);

/**
* Returns value of 'calcBigDecimalScale' from Connection String.
*
* @param calcBigDecimalScale
* indicates whether the driver should attempt to calculate scale from inputted big decimal values
*/
void setCalcBigDecimalScale(boolean calcBigDecimalScale);

/**
* Sets the value for 'calcBigDecimalScale' property
*
* @return calcBigDecimalScale boolean value
*/
boolean getCalcBigDecimalScale();
}
31 changes: 29 additions & 2 deletions src/main/java/com/microsoft/sqlserver/jdbc/Parameter.java
Original file line number Diff line number Diff line change
Expand Up @@ -531,8 +531,35 @@ private void setTypeDefinition(DTV dtv) {
param.typeDefinition = SSType.DECIMAL.toString() + "(" + valueLength + "," + scale + ")";
}
} else {
param.typeDefinition = SSType.DECIMAL.toString() + "("
+ SQLServerConnection.MAX_DECIMAL_PRECISION + "," + scale + ")";
if (con.getCalcBigDecimalScale() && dtv.getJavaType() == JavaType.BIGDECIMAL
&& null != dtv.getSetterValue()) {
String[] plainValueArray
= ((BigDecimal) dtv.getSetterValue()).abs().toPlainString().split("\\.");

// Precision is computed as opposed to using BigDecimal.precision(). This is because the
// BigDecimal method can lead to inaccurate results.

This comment has been minimized.

Copy link
@murisans

murisans Nov 24, 2023

could you please explain why BigDecimal method can lead to inaccurate results, isn't it more efficient? @Jeffery-Wasty

This comment has been minimized.

Copy link
@murisans

murisans Nov 24, 2023

public static void main(String[] args) {
        BigDecimal a = new BigDecimal(1.00);
        System.out.println(a.precision());
        System.out.println(a.scale());
    }

the scale of "1.00" seems to be zero, unless someone invoke setScale() manually

1
0
int calculatedPrecision;

// If the string array has two parts, e.g .the input was a decimal, check if the first
// part is a 0. For BigDecimals with leading zeroes, the leading zero does not count towards
// precision. For all other decimals, we include the integer portion as part of the precision
// When the string array has just one part, we only look at that part to compute precision.
if (plainValueArray.length == 2) {
if (plainValueArray[0].length() == 1 && (Integer.parseInt(plainValueArray[0]) == 0)) {
calculatedPrecision = plainValueArray[1].length();
} else {
calculatedPrecision = plainValueArray[0].length() + plainValueArray[1].length();
}
} else {
calculatedPrecision = plainValueArray[0].length();
}

param.typeDefinition = SSType.DECIMAL.toString() + "(" + calculatedPrecision + "," +
(plainValueArray.length == 2 ? plainValueArray[1].length() : 0) + ")";
} else {
param.typeDefinition = SSType.DECIMAL.toString() + "("
+ SQLServerConnection.MAX_DECIMAL_PRECISION + "," + scale + ")";
}
}
break;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -988,6 +988,18 @@ public void setIgnoreOffsetOnDateTimeOffsetConversion(boolean ignoreOffsetOnDate
this.ignoreOffsetOnDateTimeOffsetConversion = ignoreOffsetOnDateTimeOffsetConversion;
}

private boolean calcBigDecimalScale = SQLServerDriverBooleanProperty.CALC_BIG_DECIMAL_SCALE.getDefaultValue();

@Override
public boolean getCalcBigDecimalScale() {
return calcBigDecimalScale;
}

@Override
public void setCalcBigDecimalScale(boolean calcBigDecimalScale) {
this.calcBigDecimalScale = calcBigDecimalScale;
}

/** Session Recovery Object */
private transient IdleConnectionResiliency sessionRecovery = new IdleConnectionResiliency(this);

Expand Down Expand Up @@ -2078,6 +2090,15 @@ Connection connectInternal(Properties propsIn,
IPAddressPreference.valueOfString(sPropValue).toString());
}

sPropKey = SQLServerDriverBooleanProperty.CALC_BIG_DECIMAL_SCALE.toString();
sPropValue = activeConnectionProperties.getProperty(sPropKey);
if (null == sPropValue) {
sPropValue = Boolean.toString(SQLServerDriverBooleanProperty.CALC_BIG_DECIMAL_SCALE.getDefaultValue());
activeConnectionProperties.setProperty(sPropKey, sPropValue);
}

calcBigDecimalScale = isBooleanPropertyOn(sPropKey, sPropValue);

sPropKey = SQLServerDriverStringProperty.APPLICATION_NAME.toString();
sPropValue = activeConnectionProperties.getProperty(sPropKey);
if (null != sPropValue)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -691,4 +691,25 @@ public String getAccessTokenCallbackClass() {
public void setAccessTokenCallbackClass(String accessTokenCallbackClass) {
wrappedConnection.setAccessTokenCallbackClass(accessTokenCallbackClass);
}

/**
* Returns the current value for 'calcBigDecimalScale'.
*
* @return calcBigDecimalScale
* a boolean
*/
@Override
public boolean getCalcBigDecimalScale() {
return wrappedConnection.getCalcBigDecimalScale();
}

/**
* Sets the current value of 'calculateBigDecimalScale' for the driver.
*
* @param calcBigDecimalScale
*/
@Override
public void setCalcBigDecimalScale(boolean calcBigDecimalScale) {
wrappedConnection.setCalcBigDecimalScale(calcBigDecimalScale);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1326,6 +1326,29 @@ public String getAccessTokenCallbackClass() {
null);
}

/**
* Sets the 'calcBigDecimalScale' setting.
*
* @param calcBigDecimalScale
* boolean property to have the driver calculate a big decimal's scale from input
*/
@Override
public void setCalcBigDecimalScale(boolean calcBigDecimalScale) {
setBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.CALC_BIG_DECIMAL_SCALE.toString(),
calcBigDecimalScale);
}

/**
* Returns the value for 'calcBigDecimalScale'.
*
* @return computeBigDecimal boolean value
*/
@Override
public boolean getCalcBigDecimalScale() {
return getBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.CALC_BIG_DECIMAL_SCALE.toString(),
SQLServerDriverBooleanProperty.CALC_BIG_DECIMAL_SCALE.getDefaultValue());
}

/**
* Sets a property string value.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -696,7 +696,8 @@ enum SQLServerDriverBooleanProperty {
DELAY_LOADING_LOBS("delayLoadingLobs", true),
IGNORE_OFFSET_ON_DATE_TIME_OFFSET_CONVERSION("ignoreOffsetOnDateTimeOffsetConversion", false),
USE_DEFAULT_JAAS_CONFIG("useDefaultJaasConfig", false),
USE_DEFAULT_GSS_CREDENTIAL("useDefaultGSSCredential", false);
USE_DEFAULT_GSS_CREDENTIAL("useDefaultGSSCredential", false),
CALC_BIG_DECIMAL_SCALE("calcBigDecimalScale", false);

private final String name;
private final boolean defaultValue;
Expand Down Expand Up @@ -901,6 +902,9 @@ public final class SQLServerDriver implements java.sql.Driver {
new SQLServerDriverPropertyInfo(SQLServerDriverBooleanProperty.USE_DEFAULT_JAAS_CONFIG.toString(),
Boolean.toString(SQLServerDriverBooleanProperty.USE_DEFAULT_JAAS_CONFIG.getDefaultValue()), false,
TRUE_FALSE),
new SQLServerDriverPropertyInfo(SQLServerDriverBooleanProperty.CALC_BIG_DECIMAL_SCALE.toString(),
Boolean.toString(SQLServerDriverBooleanProperty.CALC_BIG_DECIMAL_SCALE.getDefaultValue()), false,
TRUE_FALSE),
new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.SSL_PROTOCOL.toString(),
SQLServerDriverStringProperty.SSL_PROTOCOL.getDefaultValue(), false,
new String[] {SSLProtocol.TLS.toString(), SSLProtocol.TLS_V10.toString(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,7 @@ protected Object[][] getContents() {
{"R_unassignableError", "The class specified by the {0} property must be assignable to {1}."},
{"R_InvalidCSVQuotes", "Failed to parse the CSV file, verify that the fields are correctly enclosed in double quotes."},
{"R_TokenRequireUrl", "Token credentials require a URL using the HTTPS protocol scheme."},
{"R_calcBigDecimalScalePropertyDescription", "Indicates whether the driver should calculate scale for big decimal values."},
{"R_maxResultBufferPropertyDescription", "Determines maximum amount of bytes that can be read during retrieval of result set"},
{"R_maxResultBufferInvalidSyntax", "Invalid syntax: {0} in maxResultBuffer parameter."},
{"R_maxResultBufferNegativeParameterValue", "MaxResultBuffer must have positive value: {0}."},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,9 @@ public void testDataSource() throws SQLServerException {
assertEquals(booleanPropValue, ds.getUseDefaultGSSCredential(),
TestResource.getResource("R_valuesAreDifferent"));

ds.setCalcBigDecimalScale(booleanPropValue);
assertEquals(booleanPropValue, ds.getCalcBigDecimalScale(), TestResource.getResource("R_valuesAreDifferent"));

ds.setServerCertificate(stringPropValue);
assertEquals(stringPropValue, ds.getServerCertificate(), TestResource.getResource("R_valuesAreDifferent"));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,8 @@ private List<String> getVerifiedMethodNames() {
verifiedMethodNames.add("setMsiTokenCacheTtl");
verifiedMethodNames.add("getAccessTokenCallbackClass");
verifiedMethodNames.add("setAccessTokenCallbackClass");
verifiedMethodNames.add("getCalcBigDecimalScale");
verifiedMethodNames.add("setCalcBigDecimalScale");
return verifiedMethodNames;
}
}
Loading

0 comments on commit 1f69f48

Please sign in to comment.