1 package com.quadcap.sql.types; 2 3 40 41 import java.io.ByteArrayOutputStream ; 42 import java.io.Externalizable ; 43 import java.io.IOException ; 44 import java.io.ObjectInput ; 45 import java.io.ObjectOutput ; 46 47 import java.math.BigDecimal ; 48 import java.math.BigInteger ; 49 50 import com.quadcap.util.Debug; 51 52 57 public class ValueScaledInteger extends Value implements Externalizable { 58 BigDecimal val; 59 60 public ValueScaledInteger() {} 61 62 public ValueScaledInteger(BigDecimal val) { 63 this.val = val; 64 } 65 66 public ValueScaledInteger(String s) throws ValueException { 67 try { 68 this.val = new BigDecimal (s); 69 return; 70 } catch (NumberFormatException e) { 71 } 72 73 s = s.trim(); 74 try { 75 this.val = new BigDecimal (s); 76 return; 77 } catch (NumberFormatException e) { 78 } 79 80 int idx = s.indexOf('E'); 81 if (idx < 0) idx = s.indexOf('e'); 82 if (idx > 0) { 83 try { 84 this.val = new BigDecimal (s.substring(0, idx)); 85 char c = s.charAt(idx+1); 86 int sign = 1; 87 if (c == '+') { 88 idx++; 89 } else if (c == '-') { 90 sign = -1; 91 idx++; 92 } 93 int exp = sign * Integer.parseInt(s.substring(idx+1)); 94 val = val.movePointRight(exp); 95 return; 96 } catch (Throwable ee) { 97 } 98 } 99 throw new ValueException("DECIMAL format error: " + s); 100 } 101 102 public ValueScaledInteger(double v) throws ValueException { 103 try { 104 this.val = new BigDecimal (v); 105 } catch (Throwable t) { 106 throw new ValueException("Bad double value: " + v); 107 } 108 109 } 110 111 public ValueScaledInteger(long v) { 112 this.val = new BigDecimal (Long.toString(v)); 113 } 114 115 public float floatValue() { return val.floatValue(); } 116 public double doubleValue() { return val.doubleValue(); } 117 118 public int requiredPrecision() { 119 String s = val.toString(); 120 if (s.startsWith("-")) s = s.substring(1); 121 int idx = s.indexOf('.'); 122 if (idx >= 0) { 123 s = s.substring(0, idx); 124 } 125 return s.length(); 126 } 127 128 public void setScale(int s) { 129 val = val.setScale(s, BigDecimal.ROUND_HALF_DOWN); 130 } 131 132 public Value binop(int op, Value l) throws ValueException { 133 return l.binop(op, this); 134 } 135 136 final Value binop(int op, long r) throws ValueException { 137 return ValueScaledInteger.binop(op, this, new ValueScaledInteger(r)); 138 } 139 140 public Value binop(int op, ValueByte r) throws ValueException { 141 return binop(op, (long)r.byteValue()); 142 } 143 144 public Value binop(int op, ValueShort r) throws ValueException { 145 return binop(op, (long)r.shortValue()); 146 } 147 148 public Value binop(int op, ValueInteger r) throws ValueException { 149 return binop(op, (long)r.intValue()); 150 } 151 152 public Value binop(int op, ValueLong r) throws ValueException { 153 return binop(op, r.longValue()); 154 } 155 156 public Value binop(int op, ValueFloat r) throws ValueException { 157 return ValueDouble.binop(op, new ValueDouble(doubleValue()), 158 new ValueDouble(r.val)); 159 } 160 161 public Value binop(int op, ValueDouble r) throws ValueException { 162 return ValueDouble.binop(op, new ValueDouble(doubleValue()), r); 163 } 164 165 public Value binop(int op, ValueNull r) throws ValueException { 166 switch (op) { 167 case Op.EQ: 168 case Op.NE: 169 case Op.LT: 170 case Op.LE: 171 case Op.GT: 172 case Op.GE: 173 return ValueUnknown.valueUnknown; 174 case Op.PLUS: 175 case Op.MINUS: 176 case Op.TIMES: 177 case Op.DIVIDE: 178 case Op.EXP: 179 return r; 180 case Op.COMPARE: 181 return r.valCmpNull(); 182 default: 183 throw badBinop(op, r); 184 } 185 } 186 187 public Value binop(int op, ValueScaledInteger r) throws ValueException { 188 return ValueScaledInteger.binop(op, this, r); 189 } 190 191 public static final Value binop(int op, ValueScaledInteger e, 192 ValueScaledInteger f) 193 throws ValueException 194 { 195 switch (op) { 196 case Op.DIVIDE: 197 try { 198 return new 203 ValueScaledInteger(e.val.divide(f.val, 204 BigDecimal.ROUND_HALF_DOWN)); 205 } catch (ArithmeticException ae) { 206 throw new ValueException("divide by zero"); 207 } 208 case Op.EQ: 209 return new ValueBoolean(0 == e.val.compareTo(f.val)); 210 case Op.EXP: 211 return new 212 ValueScaledInteger(new BigDecimal (Math.pow(e.doubleValue(), 213 f.doubleValue()))); 214 case Op.GE: 215 return new ValueBoolean(0 <= e.val.compareTo(f.val)); 216 case Op.GT: 217 return new ValueBoolean(0 < e.val.compareTo(f.val)); 218 case Op.LE: 219 return new ValueBoolean(0 >= e.val.compareTo(f.val)); 220 case Op.LT: 221 return new ValueBoolean(0 > e.val.compareTo(f.val)); 222 case Op.MINUS: 223 return new ValueScaledInteger(e.val.subtract(f.val)); 224 case Op.NE: 225 return new ValueBoolean(0 != e.val.compareTo(f.val)); 226 case Op.PLUS: 227 return new ValueScaledInteger(e.val.add(f.val)); 228 case Op.TIMES: 229 return new ValueScaledInteger(e.val.multiply(f.val)); 230 case Op.COMPARE: 231 return new ValueInteger(e.val.compareTo(f.val)); 232 233 default: 234 throw badBinop(op, e, f); 235 } 236 } 237 238 public Value unop(int op) throws ValueException { 239 switch (op) { 240 case Op.NULL: 241 return new ValueBoolean(false); 242 case Op.PLUS: 243 return this; 244 case Op.MINUS: 245 BigDecimal zero = new BigDecimal (0); 246 return new ValueScaledInteger(zero.subtract(val)); 247 default: 248 throw new ValueException("Unary op: " + Op.toString(op) + 249 " not implemented for this type"); 250 } 251 } 252 253 public void readExternal(ObjectInput in) 254 throws IOException , ClassNotFoundException 255 { 256 val = (BigDecimal )in.readObject(); 257 } 258 259 public void writeExternal(ObjectOutput out) 260 throws IOException 261 { 262 out.writeObject(val); 263 } 264 265 final public BigDecimal bigDecimalValue() { return val; } 266 267 public Object asJavaObject() { 268 return val; 269 } 270 271 public void fromJavaObject(Object obj) throws ValueException { 272 if (obj instanceof BigDecimal ) { 273 val = (BigDecimal )obj; 274 } else { 275 throw new ValueException("bad type: " + obj); 276 } 277 } 278 279 public String toString() { return val.toString(); } 280 281 public Value convert(TypeTinyInt type) throws ValueException { 282 return TypeTinyInt.convertNumber(val.doubleValue()); 283 } 284 285 public Value convert(TypeSmallInt type) throws ValueException { 286 return TypeSmallInt.convertNumber(val.doubleValue()); 287 } 288 289 public Value convert(TypeInt type) throws ValueException { 290 return TypeInt.convertNumber(val.doubleValue()); 291 } 292 293 public Value convert(TypeBigInt type) throws ValueException { 294 return TypeBigInt.convertNumber(val.doubleValue()); 295 } 296 297 public Value convert(TypeDecimal type) throws ValueException { 298 if (type.getPrecision() > 0) { 299 double lim = 300 Math.pow(10, type.getPrecision() - type.getScale()); 301 if (doubleValue() >= lim || doubleValue() <= (0-lim)) { 302 throw new ValueException("Value out of range: " + this); 303 } 304 } 305 if (val.scale() == type.getScale() || type.getScale() == -1) { 306 return this; 307 } else { 308 return new ValueScaledInteger(val.setScale(type.getScale(), 309 BigDecimal.ROUND_HALF_DOWN)); 310 } 311 } 312 313 public Value convert(TypeReal type) throws ValueException { 314 if (type.getMaxPrecision() > 31) { 315 return new ValueDouble(val.doubleValue()); 316 } else { 317 return new ValueFloat(val.floatValue()); 318 } 319 } 320 321 public Type getType() { 322 return new TypeDecimal(requiredPrecision(), val.scale()); 323 } 324 325 public void serializeKey(KeyStream out) throws IOException { 326 out.writeLength(2, KeyStream.COMPOUND); 327 BigInteger bi = val.toBigInteger(); 328 out.writeInt(bi.toByteArray()); 329 BigDecimal frac = val.subtract(new BigDecimal (bi)); 330 ByteArrayOutputStream bos = new ByteArrayOutputStream (); 331 String f = frac.toString(); 332 int accum = 0; 333 for (int i = 0; i < f.length(); i++) { 334 accum <<= 4; 335 accum |= f.charAt(i) - '0'; 336 if ((i % 2) == 1) bos.write(accum); 337 accum = 0; 338 } 339 if ((f.length() % 2) == 1) bos.write(accum); 340 out.write(bos.toByteArray()); 341 } 342 } 343 | Popular Tags |