Skip to content

Commit 1f69f48

Browse files
Allow old BigDecimal behavior via connection prop (#2248)
* 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
1 parent c64d649 commit 1f69f48

File tree

11 files changed

+365
-3
lines changed

11 files changed

+365
-3
lines changed

src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerConnection.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,4 +481,20 @@ CallableStatement prepareCall(String sql, int nType, int nConcur, int nHold,
481481
* @param accessTokenCallbackClass
482482
*/
483483
void setAccessTokenCallbackClass(String accessTokenCallbackClass);
484+
485+
/**
486+
* Returns the current flag for calcBigDecimalScale.
487+
*
488+
* @return calcBigDecimalScale
489+
* Whether calculating big decimal scale from input values is enabled.
490+
*/
491+
boolean getCalcBigDecimalScale();
492+
493+
/**
494+
* Specifies whether to calculate scale from inputted big decimal values.
495+
*
496+
* @param calcBigDecimalScale
497+
* A boolean that indicates if the driver should calculate scale from inputted big decimal values.
498+
*/
499+
void setCalcBigDecimalScale(boolean computeBigDecimal);
484500
}

src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerDataSource.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1313,4 +1313,19 @@ public interface ISQLServerDataSource extends javax.sql.CommonDataSource {
13131313
* @param accessTokenCallbackClass
13141314
*/
13151315
void setAccessTokenCallbackClass(String accessTokenCallbackClass);
1316+
1317+
/**
1318+
* Returns value of 'calcBigDecimalScale' from Connection String.
1319+
*
1320+
* @param calcBigDecimalScale
1321+
* indicates whether the driver should attempt to calculate scale from inputted big decimal values
1322+
*/
1323+
void setCalcBigDecimalScale(boolean calcBigDecimalScale);
1324+
1325+
/**
1326+
* Sets the value for 'calcBigDecimalScale' property
1327+
*
1328+
* @return calcBigDecimalScale boolean value
1329+
*/
1330+
boolean getCalcBigDecimalScale();
13161331
}

src/main/java/com/microsoft/sqlserver/jdbc/Parameter.java

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -531,8 +531,35 @@ private void setTypeDefinition(DTV dtv) {
531531
param.typeDefinition = SSType.DECIMAL.toString() + "(" + valueLength + "," + scale + ")";
532532
}
533533
} else {
534-
param.typeDefinition = SSType.DECIMAL.toString() + "("
535-
+ SQLServerConnection.MAX_DECIMAL_PRECISION + "," + scale + ")";
534+
if (con.getCalcBigDecimalScale() && dtv.getJavaType() == JavaType.BIGDECIMAL
535+
&& null != dtv.getSetterValue()) {
536+
String[] plainValueArray
537+
= ((BigDecimal) dtv.getSetterValue()).abs().toPlainString().split("\\.");
538+
539+
// Precision is computed as opposed to using BigDecimal.precision(). This is because the
540+
// BigDecimal method can lead to inaccurate results.
541+
int calculatedPrecision;
542+
543+
// If the string array has two parts, e.g .the input was a decimal, check if the first
544+
// part is a 0. For BigDecimals with leading zeroes, the leading zero does not count towards
545+
// precision. For all other decimals, we include the integer portion as part of the precision
546+
// When the string array has just one part, we only look at that part to compute precision.
547+
if (plainValueArray.length == 2) {
548+
if (plainValueArray[0].length() == 1 && (Integer.parseInt(plainValueArray[0]) == 0)) {
549+
calculatedPrecision = plainValueArray[1].length();
550+
} else {
551+
calculatedPrecision = plainValueArray[0].length() + plainValueArray[1].length();
552+
}
553+
} else {
554+
calculatedPrecision = plainValueArray[0].length();
555+
}
556+
557+
param.typeDefinition = SSType.DECIMAL.toString() + "(" + calculatedPrecision + "," +
558+
(plainValueArray.length == 2 ? plainValueArray[1].length() : 0) + ")";
559+
} else {
560+
param.typeDefinition = SSType.DECIMAL.toString() + "("
561+
+ SQLServerConnection.MAX_DECIMAL_PRECISION + "," + scale + ")";
562+
}
536563
}
537564
break;
538565

src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -988,6 +988,18 @@ public void setIgnoreOffsetOnDateTimeOffsetConversion(boolean ignoreOffsetOnDate
988988
this.ignoreOffsetOnDateTimeOffsetConversion = ignoreOffsetOnDateTimeOffsetConversion;
989989
}
990990

991+
private boolean calcBigDecimalScale = SQLServerDriverBooleanProperty.CALC_BIG_DECIMAL_SCALE.getDefaultValue();
992+
993+
@Override
994+
public boolean getCalcBigDecimalScale() {
995+
return calcBigDecimalScale;
996+
}
997+
998+
@Override
999+
public void setCalcBigDecimalScale(boolean calcBigDecimalScale) {
1000+
this.calcBigDecimalScale = calcBigDecimalScale;
1001+
}
1002+
9911003
/** Session Recovery Object */
9921004
private transient IdleConnectionResiliency sessionRecovery = new IdleConnectionResiliency(this);
9931005

@@ -2078,6 +2090,15 @@ Connection connectInternal(Properties propsIn,
20782090
IPAddressPreference.valueOfString(sPropValue).toString());
20792091
}
20802092

2093+
sPropKey = SQLServerDriverBooleanProperty.CALC_BIG_DECIMAL_SCALE.toString();
2094+
sPropValue = activeConnectionProperties.getProperty(sPropKey);
2095+
if (null == sPropValue) {
2096+
sPropValue = Boolean.toString(SQLServerDriverBooleanProperty.CALC_BIG_DECIMAL_SCALE.getDefaultValue());
2097+
activeConnectionProperties.setProperty(sPropKey, sPropValue);
2098+
}
2099+
2100+
calcBigDecimalScale = isBooleanPropertyOn(sPropKey, sPropValue);
2101+
20812102
sPropKey = SQLServerDriverStringProperty.APPLICATION_NAME.toString();
20822103
sPropValue = activeConnectionProperties.getProperty(sPropKey);
20832104
if (null != sPropValue)

src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionPoolProxy.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -691,4 +691,25 @@ public String getAccessTokenCallbackClass() {
691691
public void setAccessTokenCallbackClass(String accessTokenCallbackClass) {
692692
wrappedConnection.setAccessTokenCallbackClass(accessTokenCallbackClass);
693693
}
694+
695+
/**
696+
* Returns the current value for 'calcBigDecimalScale'.
697+
*
698+
* @return calcBigDecimalScale
699+
* a boolean
700+
*/
701+
@Override
702+
public boolean getCalcBigDecimalScale() {
703+
return wrappedConnection.getCalcBigDecimalScale();
704+
}
705+
706+
/**
707+
* Sets the current value of 'calculateBigDecimalScale' for the driver.
708+
*
709+
* @param calcBigDecimalScale
710+
*/
711+
@Override
712+
public void setCalcBigDecimalScale(boolean calcBigDecimalScale) {
713+
wrappedConnection.setCalcBigDecimalScale(calcBigDecimalScale);
714+
}
694715
}

src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSource.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1326,6 +1326,29 @@ public String getAccessTokenCallbackClass() {
13261326
null);
13271327
}
13281328

1329+
/**
1330+
* Sets the 'calcBigDecimalScale' setting.
1331+
*
1332+
* @param calcBigDecimalScale
1333+
* boolean property to have the driver calculate a big decimal's scale from input
1334+
*/
1335+
@Override
1336+
public void setCalcBigDecimalScale(boolean calcBigDecimalScale) {
1337+
setBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.CALC_BIG_DECIMAL_SCALE.toString(),
1338+
calcBigDecimalScale);
1339+
}
1340+
1341+
/**
1342+
* Returns the value for 'calcBigDecimalScale'.
1343+
*
1344+
* @return computeBigDecimal boolean value
1345+
*/
1346+
@Override
1347+
public boolean getCalcBigDecimalScale() {
1348+
return getBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.CALC_BIG_DECIMAL_SCALE.toString(),
1349+
SQLServerDriverBooleanProperty.CALC_BIG_DECIMAL_SCALE.getDefaultValue());
1350+
}
1351+
13291352
/**
13301353
* Sets a property string value.
13311354
*

src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -696,7 +696,8 @@ enum SQLServerDriverBooleanProperty {
696696
DELAY_LOADING_LOBS("delayLoadingLobs", true),
697697
IGNORE_OFFSET_ON_DATE_TIME_OFFSET_CONVERSION("ignoreOffsetOnDateTimeOffsetConversion", false),
698698
USE_DEFAULT_JAAS_CONFIG("useDefaultJaasConfig", false),
699-
USE_DEFAULT_GSS_CREDENTIAL("useDefaultGSSCredential", false);
699+
USE_DEFAULT_GSS_CREDENTIAL("useDefaultGSSCredential", false),
700+
CALC_BIG_DECIMAL_SCALE("calcBigDecimalScale", false);
700701

701702
private final String name;
702703
private final boolean defaultValue;
@@ -901,6 +902,9 @@ public final class SQLServerDriver implements java.sql.Driver {
901902
new SQLServerDriverPropertyInfo(SQLServerDriverBooleanProperty.USE_DEFAULT_JAAS_CONFIG.toString(),
902903
Boolean.toString(SQLServerDriverBooleanProperty.USE_DEFAULT_JAAS_CONFIG.getDefaultValue()), false,
903904
TRUE_FALSE),
905+
new SQLServerDriverPropertyInfo(SQLServerDriverBooleanProperty.CALC_BIG_DECIMAL_SCALE.toString(),
906+
Boolean.toString(SQLServerDriverBooleanProperty.CALC_BIG_DECIMAL_SCALE.getDefaultValue()), false,
907+
TRUE_FALSE),
904908
new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.SSL_PROTOCOL.toString(),
905909
SQLServerDriverStringProperty.SSL_PROTOCOL.getDefaultValue(), false,
906910
new String[] {SSLProtocol.TLS.toString(), SSLProtocol.TLS_V10.toString(),

src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,7 @@ protected Object[][] getContents() {
515515
{"R_unassignableError", "The class specified by the {0} property must be assignable to {1}."},
516516
{"R_InvalidCSVQuotes", "Failed to parse the CSV file, verify that the fields are correctly enclosed in double quotes."},
517517
{"R_TokenRequireUrl", "Token credentials require a URL using the HTTPS protocol scheme."},
518+
{"R_calcBigDecimalScalePropertyDescription", "Indicates whether the driver should calculate scale for big decimal values."},
518519
{"R_maxResultBufferPropertyDescription", "Determines maximum amount of bytes that can be read during retrieval of result set"},
519520
{"R_maxResultBufferInvalidSyntax", "Invalid syntax: {0} in maxResultBuffer parameter."},
520521
{"R_maxResultBufferNegativeParameterValue", "MaxResultBuffer must have positive value: {0}."},

src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,9 @@ public void testDataSource() throws SQLServerException {
205205
assertEquals(booleanPropValue, ds.getUseDefaultGSSCredential(),
206206
TestResource.getResource("R_valuesAreDifferent"));
207207

208+
ds.setCalcBigDecimalScale(booleanPropValue);
209+
assertEquals(booleanPropValue, ds.getCalcBigDecimalScale(), TestResource.getResource("R_valuesAreDifferent"));
210+
208211
ds.setServerCertificate(stringPropValue);
209212
assertEquals(stringPropValue, ds.getServerCertificate(), TestResource.getResource("R_valuesAreDifferent"));
210213

src/test/java/com/microsoft/sqlserver/jdbc/connection/RequestBoundaryMethodsTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,8 @@ private List<String> getVerifiedMethodNames() {
509509
verifiedMethodNames.add("setMsiTokenCacheTtl");
510510
verifiedMethodNames.add("getAccessTokenCallbackClass");
511511
verifiedMethodNames.add("setAccessTokenCallbackClass");
512+
verifiedMethodNames.add("getCalcBigDecimalScale");
513+
verifiedMethodNames.add("setCalcBigDecimalScale");
512514
return verifiedMethodNames;
513515
}
514516
}

0 commit comments

Comments
 (0)