001: package simpleorm.core;
002:
003: import simpleorm.properties.*;
004: import java.sql.ResultSet;
005: import java.math.BigDecimal;
006:
007: /** Represents BigDecimal field meta data. Default SQL type is
008: NUMERIC(precission, scale), which is roughly sql-92.<p>
009:
010: What is the best way to represent money ammounts exactly? Scaled
011: longs are no good for direct end user queries on the database.
012: Doubles tend to loose precission due to Java truncating instead of
013: rounding -- things will not balance. And BigDecimals are
014: inefficient and a real pain to use. Your choice.
015:
016: */
017: public class SFieldBigDecimal extends SFieldScalar {
018: /** Note that precission and scale parameters only affect how the
019: tables are created. The scale that is actually returned is up
020: to JDBC. And then you are responsible for dealing with rounding
021: issues. */
022: public SFieldBigDecimal(SRecordMeta meta, String columnName,
023: int precission, int scale, SPropertyValue[] pvals) {
024: super (meta, columnName, pvals);
025: putProperty(SCon.SDECIMAL_PRECISION, SJSharp
026: .newInteger(precission));
027: putProperty(SCon.SDECIMAL_SCALE, SJSharp.newInteger(scale));
028: }
029:
030: public SFieldBigDecimal(SRecordMeta meta, String columnName,
031: int precission, int scale) {
032: this (meta, columnName, precission, scale, new SPropertyValue[0]);
033: }
034:
035: public SFieldBigDecimal(SRecordMeta meta, String columnName,
036: int precission, int scale, SPropertyValue pval) {
037: this (meta, columnName, precission, scale,
038: new SPropertyValue[] { pval });
039: }
040:
041: public SFieldBigDecimal(SRecordMeta meta, String columnName,
042: int precission, int scale, SPropertyValue pval1,
043: SPropertyValue pval2) {
044: this (meta, columnName, precission, scale, new SPropertyValue[] {
045: pval1, pval2 });
046: }
047:
048: /** Abstract specializer. Clone this key field to be a foreign key
049: to <code>rmeta</code> of the same type.*/
050: SFieldMeta makeForeignKey(SRecordMeta rmeta, String prefix,
051: SPropertyValue[] pvals) {
052: return new SFieldBigDecimal(rmeta, (prefix == null ? ""
053: : prefix)
054: + getString(SCon.SCOLUMN_NAME), SJSharp
055: .object2Int(getProperty(SCon.SDECIMAL_PRECISION)),
056: SJSharp.object2Int(getProperty(SCon.SDECIMAL_SCALE)),
057: pvals);
058: }
059:
060: Object queryFieldValue(ResultSet rs, int sqlIndex) throws Exception {
061: /**
062: * CHANGED to add second parameter
063: */
064: BigDecimal res = rs.getBigDecimal(sqlIndex, SJSharp
065: .object2Int(this .getProperty(SCon.SDECIMAL_SCALE)));
066: if (rs.wasNull()) // ie. last operation!
067: return null;
068: else
069: return res;
070: }
071:
072: Object convertToField(Object raw) throws Exception {
073: if (raw instanceof BigDecimal)
074: return (BigDecimal) raw;
075: if (raw == null)
076: return null;
077: if (raw instanceof Number)
078: return new BigDecimal(((Number) raw).doubleValue());
079: // ## This will loose precission for longs, but Java does not
080: // provide an easy way to convert longs to BigDecimals! There is
081: // certainly no Number.bigDecimalValue.
082: if (raw instanceof String) {
083: BigDecimal val = new BigDecimal((String) raw);
084: return val;
085: }
086: throw new SException.Data("Cannot convert " + raw
087: + " to BigDecimal.");
088: }
089:
090: /** Specializes SFieldMeta. This is basically SQL 2, and fairly
091: database independent, we hope. Note that "BIGDECIMAL" for Oracle
092: means a text field that can contain over 2K characters! */
093: String defaultDataType() {
094: return "NUMERIC("
095: + SJSharp
096: .object2Int(getProperty(SCon.SDECIMAL_PRECISION))
097: + ","
098: + SJSharp.object2Int(getProperty(SCon.SDECIMAL_SCALE))
099: + ")";
100: }
101:
102: }
|