1 5 package org.h2.value; 6 7 import java.math.BigDecimal ; 8 import java.sql.PreparedStatement ; 9 import java.sql.SQLException ; 10 11 import org.h2.message.Message; 12 import org.h2.util.MathUtils; 13 14 17 public class ValueDecimal extends Value { 18 private BigDecimal value; 20 private String valueString; 21 private int precision; 22 23 private static final BigDecimal DEC_ZERO = new BigDecimal ("0"); 24 private static final BigDecimal DEC_ONE = new BigDecimal ("1"); 25 private static final ValueDecimal ZERO = new ValueDecimal(DEC_ZERO); 26 private static final ValueDecimal ONE = new ValueDecimal(DEC_ONE); 27 28 public static final int DEFAULT_PRECISION = 65535; 29 public static final int DEFAULT_SCALE = 32767; 30 private static final int DIVIDE_SCALE_ADD = 25; 31 32 private ValueDecimal(BigDecimal value) { 33 if (value == null) { 34 throw new NullPointerException (); 35 } else if(!value.getClass().equals(BigDecimal .class)) { 36 SQLException e = Message.getSQLException(Message.INVALID_CLASS_2, new String []{BigDecimal .class.getName(), value.getClass().getName()}, null); 37 throw Message.convertToInternal(e); 38 } 39 this.value = value; 40 } 41 42 public Value add(Value v) { 43 ValueDecimal dec = (ValueDecimal) v; 44 return ValueDecimal.get(value.add(dec.value)); 45 } 46 47 public Value subtract(Value v) { 48 ValueDecimal dec = (ValueDecimal) v; 49 return ValueDecimal.get(value.subtract(dec.value)); 50 } 51 52 public Value negate() { 53 return ValueDecimal.get(value.negate()); 54 } 55 56 public Value multiply(Value v) { 57 ValueDecimal dec = (ValueDecimal) v; 58 return ValueDecimal.get(value.multiply(dec.value)); 59 } 60 61 public Value divide(Value v) throws SQLException { 62 ValueDecimal dec = (ValueDecimal) v; 63 if (dec.value.signum() == 0) { 65 throw Message.getSQLException(Message.DIVISION_BY_ZERO_1, getSQL()); 66 } 67 BigDecimal bd = value.divide(dec.value, value.scale()+DIVIDE_SCALE_ADD, BigDecimal.ROUND_HALF_DOWN); 68 if(bd.signum()==0) { 69 bd = DEC_ZERO; 70 } else if(bd.scale()>0) { 71 if(!bd.unscaledValue().testBit(0)) { 72 String s = bd.toString(); 73 int i=s.length() - 1; 74 while(i>=0 && s.charAt(i) == '0') { 75 i--; 76 } 77 if(i < s.length() - 1) { 78 s = s.substring(0, i+1); 79 bd = new BigDecimal (s); 80 } 81 } 82 } 83 return ValueDecimal.get(bd); 84 } 85 86 public String getSQL() { 87 return getString(); 88 } 89 90 public int getType() { 91 return Value.DECIMAL; 92 } 93 94 protected int compareSecure(Value o, CompareMode mode) { 95 ValueDecimal v = (ValueDecimal) o; 96 int c = value.compareTo(v.value); 97 return c == 0 ? 0 : (c < 0 ? -1 : 1); 98 } 99 100 public int getSignum() { 101 return value.signum(); 102 } 103 104 public BigDecimal getBigDecimal() { 105 return value; 106 } 107 108 public String getString() { 109 if(valueString == null) { 110 valueString = value.toString(); 111 } 112 return valueString; 113 } 114 115 public long getPrecision() { 116 if(precision == 0) { 117 precision = value.unscaledValue().abs().toString().length(); 118 } 119 return precision; 120 } 121 122 public int getScale() { 123 return value.scale(); 124 } 125 126 public int hashCode() { 127 return value.hashCode(); 128 } 129 130 public Object getObject() { 131 return value; 132 } 133 134 public void set(PreparedStatement prep, int parameterIndex) throws SQLException { 135 prep.setBigDecimal(parameterIndex, value); 136 } 137 138 public Value convertScale(boolean onlyToSmallerScale, int targetScale) throws SQLException { 139 if (value.scale() == targetScale) { 140 return this; 141 } 142 if (onlyToSmallerScale || targetScale >= DEFAULT_SCALE) { 143 if (value.scale() < targetScale) { 144 return this; 145 } 146 } 147 BigDecimal bd = MathUtils.setScale(value, targetScale); 148 return ValueDecimal.get(bd); 149 } 150 151 public Value convertPrecision(long precision) throws SQLException { 152 if (getPrecision() <= precision) { 153 return this; 154 } 155 throw Message.getSQLException(Message.VALUE_TOO_LARGE_FOR_PRECISION_1, "" + precision); 156 } 157 158 public static ValueDecimal get(BigDecimal dec) { 159 if (DEC_ZERO.equals(dec)) { 160 return ZERO; 161 } else if (DEC_ONE.equals(dec)) { 162 return ONE; 163 } 164 return (ValueDecimal) Value.cache(new ValueDecimal(dec)); 167 } 168 169 173 public int getDisplaySize() { 174 return getString().length(); 176 } 177 178 protected boolean isEqual(Value v) { 179 return v instanceof ValueDecimal && value.equals(((ValueDecimal)v).value); 180 } 181 182 } 183 | Popular Tags |