package simpleorm.core;
import simpleorm.properties.*;
import java.sql.ResultSet;
import java.math.BigDecimal;
/** Represents BigDecimal field meta data. Default SQL type is
NUMERIC(precission, scale), which is roughly sql-92.<p>
What is the best way to represent money ammounts exactly? Scaled
longs are no good for direct end user queries on the database.
Doubles tend to loose precission due to Java truncating instead of
rounding -- things will not balance. And BigDecimals are
inefficient and a real pain to use. Your choice.
*/
public class SFieldBigDecimal extends SFieldScalar {
/** Note that precission and scale parameters only affect how the
tables are created. The scale that is actually returned is up
to JDBC. And then you are responsible for dealing with rounding
issues. */
public SFieldBigDecimal(SRecordMeta meta, String columnName,
int precission, int scale, SPropertyValue [] pvals) {
super(meta, columnName, pvals);
putProperty(SCon.SDECIMAL_PRECISION, SJSharp.newInteger(precission));
putProperty(SCon.SDECIMAL_SCALE, SJSharp.newInteger(scale));
}
public SFieldBigDecimal(SRecordMeta meta, String columnName,
int precission, int scale) {
this(meta, columnName, precission, scale, new SPropertyValue[0]);
}
public SFieldBigDecimal(SRecordMeta meta, String columnName,
int precission, int scale, SPropertyValue pval) {
this(meta, columnName, precission, scale, new SPropertyValue[]{pval});
}
public SFieldBigDecimal(SRecordMeta meta, String columnName,
int precission, int scale, SPropertyValue pval1, SPropertyValue pval2) {
this(meta, columnName, precission, scale,
new SPropertyValue[]{pval1, pval2});
}
/** Abstract specializer. Clone this key field to be a foreign key
to <code>rmeta</code> of the same type.*/
SFieldMeta makeForeignKey(
SRecordMeta rmeta, String prefix, SPropertyValue [] pvals) {
return new SFieldBigDecimal(rmeta,
(prefix==null?"":prefix)+getString(SCon.SCOLUMN_NAME),
SJSharp.object2Int(getProperty(SCon.SDECIMAL_PRECISION)),
SJSharp.object2Int(getProperty(SCon.SDECIMAL_SCALE)),
pvals);
}
Object queryFieldValue(ResultSet rs, int sqlIndex) throws Exception {
/**
* CHANGED to add second parameter
*/
BigDecimal res = rs.getBigDecimal(sqlIndex,
SJSharp.object2Int(this.getProperty(SCon.SDECIMAL_SCALE)) );
if (rs.wasNull()) // ie. last operation!
return null;
else
return res;
}
Object convertToField(Object raw) throws Exception {
if (raw instanceof BigDecimal) return (BigDecimal) raw;
if (raw == null) return null;
if (raw instanceof Number)
return new BigDecimal(((Number)raw).doubleValue());
// ## This will loose precission for longs, but Java does not
// provide an easy way to convert longs to BigDecimals! There is
// certainly no Number.bigDecimalValue.
if (raw instanceof String) {
BigDecimal val = new BigDecimal((String)raw);
return val;
}
throw new SException.Data("Cannot convert " + raw + " to BigDecimal.");
}
/** Specializes SFieldMeta. This is basically SQL 2, and fairly
database independent, we hope. Note that "BIGDECIMAL" for Oracle
means a text field that can contain over 2K characters! */
String defaultDataType(){
return "NUMERIC(" +
SJSharp.object2Int(getProperty(SCon.SDECIMAL_PRECISION)) + "," +
SJSharp.object2Int(getProperty(SCon.SDECIMAL_SCALE)) + ")";}
}
|