/*
* Microsoft JDBC Driver for SQL Server
*
* Copyright(c) Microsoft Corporation All rights reserved.
*
* This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information.
*/
package com.microsoft.sqlserver.testframework.sqlType;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.JDBCType;
import java.util.concurrent.ThreadLocalRandom;
public class SqlDecimal extends SqlType {
// TODO:add overloaded consturtcor to avoid resetting scale and preccision
public SqlDecimal() {
this("decimal", JDBCType.DECIMAL);
}
// called for decimal and numeric type
SqlDecimal(String name,
JDBCType jdbctype) {
this(name, jdbctype, 38, 0, SqlTypeValue.DECIMAL.minValue, SqlTypeValue.DECIMAL.maxValue, VariableLengthType.Scale);
}
// called from money/smallmoney
SqlDecimal(String name,
int precision,
int scale,
Object min,
Object max,
VariableLengthType variableLengthType) {
this(name, JDBCType.DECIMAL, precision, scale, min, max, variableLengthType);
}
SqlDecimal(String name,
JDBCType jdbctype,
int precision,
int scale,
Object min,
Object max,
VariableLengthType variableLengthType) {
super(name, jdbctype, precision, scale, min, max, SqlTypeValue.DECIMAL.nullValue, variableLengthType, BigDecimal.class);
// update random precision and scale
generatePrecision();
int minScale = 0;
int maxScale = this.precision;
// for money and smallmoney, valid max scale should be smallest of (4 or
// precision)
if (0 != this.scale) {
maxScale = (this.scale <= this.precision) ? this.scale : this.precision;
}
this.scale = ThreadLocalRandom.current().nextInt(minScale, maxScale + 1);
}
public Object createdata() {
double lowerBound = 0;
double upperBound = 1;
/**
* value to add for Math.random() to include upperBound - to choose random value between 0 to 1 (inclusive of both)
*/
double incrementValue = 0.1d;
Boolean inValidData = true;
BigDecimal randomValue = null;
while (inValidData) {
randomValue = new BigDecimal(ThreadLocalRandom.current().nextDouble(lowerBound, upperBound + incrementValue));
Boolean isNegative = (0 == ThreadLocalRandom.current().nextInt(2)) ? true : false;
// Restrict the BigInteger to the length of precision
// i.e., if the precision is say 5, then get unscaledRandom%10^5
if (randomValue.compareTo(new BigDecimal("1")) >= 0) {
randomValue = randomValue.movePointRight(precision - scale - 1);
}
else {
randomValue = randomValue.movePointRight(precision - scale);
}
randomValue = randomValue.setScale(scale, RoundingMode.FLOOR);
randomValue = (isNegative) ? randomValue.multiply(new BigDecimal("-1")) : randomValue;
// must be 0 or -ve
int exceedsMax = randomValue.compareTo((BigDecimal) maxvalue);
// must be 0 or +ve
int exceedsMin = randomValue.compareTo((BigDecimal) minvalue);
// recursion if data generated is < than min accepted value or >
// than max bigdecimal
if (!((exceedsMin < 0) || (exceedsMax > 0))) {
inValidData = false;
}
}
return randomValue;
}
}