1 21 22 package org.apache.derby.iapi.types; 23 24 import java.math.BigInteger ; 25 import java.sql.Types ; 26 27 import org.apache.derby.iapi.error.StandardException; 28 import org.apache.derby.iapi.reference.SQLState; 29 import org.apache.derby.iapi.services.sanity.SanityManager; 30 31 41 42 public final class BigIntegerDecimal extends BinaryDecimal 43 { 44 private static final BigInteger TEN = BigInteger.valueOf(10L); 45 private static final BigInteger MAXLONG_PLUS_ONE = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE); 46 private static final BigInteger MINLONG_MINUS_ONE = BigInteger.valueOf(Long.MIN_VALUE).subtract(BigInteger.ONE); 47 48 public BigIntegerDecimal() { 49 } 50 51 public DataValueDescriptor getNewNull() 52 { 53 return new BigIntegerDecimal(); 54 } 55 56 public long getLong() throws StandardException 57 { 58 if (isNull()) 59 return 0L; 60 61 BigInteger bi = new BigInteger (data2c); 62 63 boolean rangeOk = false; 67 if ((bi.compareTo(BigIntegerDecimal.MAXLONG_PLUS_ONE) < 0) 68 && (bi.compareTo(BigIntegerDecimal.MINLONG_MINUS_ONE) > 0)) 69 rangeOk = true; 70 71 for (int i = 0; i < sqlScale; i++) 72 { 73 bi = bi.divide(BigIntegerDecimal.TEN); 74 if (rangeOk) 75 continue; 76 77 if ((bi.compareTo(BigIntegerDecimal.MAXLONG_PLUS_ONE) < 0) 78 && (bi.compareTo(BigIntegerDecimal.MINLONG_MINUS_ONE) > 0)) 79 rangeOk = true; 80 } 81 82 if (!rangeOk) 84 throw StandardException.newException(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE, "BIGINT"); 85 86 return bi.longValue(); 87 } 88 89 public float getFloat() throws StandardException 90 { 91 if (isNull()) 92 return 0.0f; 93 return NumberDataType.normalizeREAL(Float.parseFloat(getString())); 94 } 95 public double getDouble() throws StandardException 96 { 97 if (isNull()) 98 return 0.0; 99 return NumberDataType.normalizeDOUBLE(Double.parseDouble(getString())); 100 } 101 102 public boolean getBoolean() 104 { 105 if (isNull()) 106 return false; 107 108 BigInteger bi = new BigInteger (data2c); 109 return bi.compareTo(java.math.BigInteger.ZERO) != 0; 110 } 111 112 118 public void setValue(String theValue) throws StandardException 119 { 120 if (theValue == null) 121 { 122 restoreToNull(); 123 return; 124 } 125 126 theValue = theValue.trim(); 127 128 int dot = theValue.indexOf('.'); 129 int ePosition = theValue.indexOf('e'); 130 if (ePosition == -1) 131 ePosition = theValue.indexOf('E'); 132 133 134 int scale = 0; 135 try 136 { 137 if (ePosition != -1) 139 { 140 if (dot > ePosition) 141 throw invalidFormat(); 142 143 147 int expOffset = ePosition + 1; 148 149 if (expOffset >= theValue.length()) 150 throw invalidFormat(); 151 152 if (theValue.charAt(expOffset) == '+') 153 { 154 expOffset++; 158 if (expOffset >= theValue.length()) 159 throw invalidFormat(); 160 if (theValue.charAt(expOffset) == '-') 161 throw invalidFormat(); 162 } 163 164 String exponent = theValue.substring(expOffset); 165 166 scale = -1 * Integer.parseInt(exponent); 167 theValue = theValue.substring(0, ePosition); 168 } 169 170 if (dot != -1) 171 { 172 String leading = theValue.substring(0, dot); 174 175 scale += (theValue.length() - (dot + 1)); 176 177 theValue = leading.concat(theValue.substring(dot + 1, theValue.length())); 178 } 179 180 if (scale < 0) 181 { 182 for (int i = scale; i < 0; i++) 183 theValue = theValue.concat("0"); 184 scale = 0; 185 } 186 187 BigInteger bi = new BigInteger (theValue); 188 data2c = bi.toByteArray(); 189 sqlScale = scale; 190 191 } catch (NumberFormatException nfe) 192 { 193 throw invalidFormat(); 194 } 195 } 196 197 198 201 public String getString() { 202 203 if (isNull()) 204 return null; 205 206 String unscaled = new BigInteger (data2c).toString(); 207 208 if (sqlScale == 0) 209 return unscaled; 210 211 boolean isNegative = this.isNegative(); 212 213 if (sqlScale >= (unscaled.length() - (isNegative ? 1 : 0))) 214 { 215 if (isNegative) 216 unscaled = unscaled.substring(1); 217 218 String val = isNegative ? "-0." : "0."; 219 for (int i = sqlScale - unscaled.length(); i > 0; i--) 220 val = val.concat("0"); 221 return val.concat(unscaled); 222 } 223 224 String val = unscaled.substring(0, unscaled.length() - sqlScale); 225 val = val.concat("."); 226 return val.concat(unscaled.substring(unscaled.length() - sqlScale, unscaled.length())); 227 } 228 229 232 public int getDecimalValuePrecision() 233 { 234 if (isNull()) 235 return 0; 236 237 BigInteger bi = new BigInteger (data2c); 238 239 if (BigInteger.ZERO.equals(bi)) 240 return 0; 241 242 int precision = bi.toString().length(); 243 244 if (this.isNegative()) 245 precision--; 246 247 if (precision < sqlScale) 248 return sqlScale; 249 250 return precision; 251 } 252 253 254 257 protected int typeCompare(DataValueDescriptor arg) throws StandardException { 258 259 BigIntegerDecimal obid = getBID(arg); 260 261 int tscale = getDecimalValueScale(); 263 int oscale = obid.getDecimalValueScale(); 264 265 BigInteger tbi = new BigInteger (data2c); 266 BigInteger obi = new BigInteger (obid.data2c); 267 268 if (tscale < oscale) 269 tbi = BigIntegerDecimal.rescale(tbi, oscale - tscale); 270 else if (oscale < tscale) 271 obi = BigIntegerDecimal.rescale(obi, tscale - oscale); 272 273 return tbi.compareTo(obi); 274 } 275 276 280 public NumberDataValue plusNN(NumberDataValue left, NumberDataValue right, NumberDataValue result) 281 throws StandardException { 282 283 BinaryDecimal resultBid = (BinaryDecimal) result; 284 if (resultBid == null) 285 resultBid = new BigIntegerDecimal(); 286 287 BigIntegerDecimal lbid = getBID(left); 288 BigIntegerDecimal rbid = getBID(right); 289 290 int lscale = lbid.getDecimalValueScale(); 292 int rscale = rbid.getDecimalValueScale(); 293 294 BigInteger bi1 = new BigInteger (lbid.data2c); 295 BigInteger bi2 = new BigInteger (rbid.data2c); 296 297 int tscale = lscale; 298 if (lscale < rscale) 299 { 300 bi1 = BigIntegerDecimal.rescale(bi1, rscale - lscale); 301 tscale = rscale; 302 } 303 else if (rscale < lscale) 304 { 305 bi2 = BigIntegerDecimal.rescale(bi2, lscale - rscale); 306 } 307 308 309 310 bi1 = bi1.add(bi2); 311 312 resultBid.data2c = bi1.toByteArray(); 313 resultBid.sqlScale = tscale; 314 315 return resultBid; 316 } 317 318 322 public NumberDataValue minus(NumberDataValue result) throws StandardException { 323 324 if (result == null) 325 result = (NumberDataValue) getNewNull(); 326 327 if (isNull()) 328 result.setToNull(); 329 else 330 { 331 BinaryDecimal rbd = (BinaryDecimal) result; 332 333 BigInteger bi = new BigInteger (data2c); 334 rbd.data2c = bi.negate().toByteArray(); 336 rbd.sqlScale = sqlScale; 337 338 } 339 340 return result; 341 } 342 343 344 356 public NumberDataValue timesNN(NumberDataValue left, NumberDataValue right, NumberDataValue result) 357 throws StandardException 358 { 359 BigIntegerDecimal resultBid = (BigIntegerDecimal) result; 360 if (resultBid == null) 361 resultBid = new BigIntegerDecimal(); 362 363 BigIntegerDecimal lbid = getBID(left); 364 BigIntegerDecimal rbid = getBID(right); 365 366 BigInteger lbi = new BigInteger (lbid.data2c); 367 BigInteger rbi = new BigInteger (rbid.data2c); 368 369 rbi = lbi.multiply(rbi); 370 resultBid.data2c = rbi.toByteArray(); 371 resultBid.sqlScale = lbid.getDecimalValueScale() + rbid.getDecimalValueScale(); 372 373 return resultBid; 374 } 375 376 388 public NumberDataValue divideNN(NumberDataValue left, NumberDataValue right, 389 NumberDataValue result, int scale) 390 throws StandardException 391 { 392 BinaryDecimal resultBid = (BinaryDecimal) result; 393 if (resultBid == null) 394 resultBid = new BigIntegerDecimal(); 395 396 BigIntegerDecimal lbid = getBID(left); 397 BigIntegerDecimal rbid = getBID(right); 398 399 BigInteger lbi = new BigInteger (lbid.data2c); 400 BigInteger rbi = new BigInteger (rbid.data2c); 401 402 if (BigInteger.ZERO.equals(rbi)) 403 throw StandardException.newException(SQLState.LANG_DIVIDE_BY_ZERO); 404 405 int lscale = lbid.getDecimalValueScale(); 406 int rscale = rbid.getDecimalValueScale(); 407 408 if (scale >= 0) 409 { 410 if (lscale < (scale + rscale)) { 411 lbi = BigIntegerDecimal.rescale(lbi, scale + rscale - lscale); 412 lscale = scale + rscale; 413 } 414 } 415 416 rbi = lbi.divide(rbi); 417 resultBid.sqlScale = lscale - rscale; 418 419 if (resultBid.sqlScale < 0) 420 { 421 rbi = BigIntegerDecimal.rescale(rbi, -resultBid.sqlScale); 422 resultBid.sqlScale = 0; 423 } 424 425 resultBid.data2c = rbi.toByteArray(); 426 427 return resultBid; 428 } 429 430 public void normalize( 431 DataTypeDescriptor desiredType, 432 DataValueDescriptor source) 433 throws StandardException 434 { 435 int desiredScale = desiredType.getScale(); 436 int desiredPrecision = desiredType.getPrecision(); 437 438 setFrom(source); 439 setWidth(desiredPrecision, desiredScale, true); 440 } 441 442 445 public void setWidth(int desiredPrecision, int desiredScale, 446 boolean errorOnTrunc) throws StandardException 447 { 448 if (isNull()) 449 return; 450 451 int deltaScale = desiredScale - sqlScale; 452 if (desiredPrecision != IGNORE_PRECISION) 453 { 454 int currentPrecision = getDecimalValuePrecision(); 455 456 int futurePrecision = currentPrecision + deltaScale; 457 458 if (futurePrecision > desiredPrecision) 459 throw StandardException.newException(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE, 460 ("DECIMAL/NUMERIC("+desiredPrecision+","+desiredScale+")")); 461 } 462 463 if (deltaScale == 0) 464 return; 465 466 BigInteger bi = new BigInteger (data2c); 467 468 bi = BigIntegerDecimal.rescale(bi, deltaScale); 469 470 data2c = bi.toByteArray(); 471 sqlScale = desiredScale; 472 } 473 474 477 private BigIntegerDecimal getBID(DataValueDescriptor value) 478 throws StandardException 479 { 480 switch (value.typeToBigDecimal()) { 481 case Types.DECIMAL: 482 return (BigIntegerDecimal) value; 483 case Types.CHAR: { 484 BigIntegerDecimal bid = new BigIntegerDecimal(); 485 bid.setValue(value.getString()); 486 return bid; 487 } 488 489 case Types.BIGINT: { 490 BigIntegerDecimal bid = new BigIntegerDecimal(); 491 bid.setValue(value.getLong()); 492 return bid; 493 } 494 default: 495 if (SanityManager.DEBUG) 496 SanityManager.THROWASSERT("invalid return from " 497 + value.getClass() + ".typeToBigDecimal() " 498 + value.typeToBigDecimal()); 499 return null; 500 } 501 } 502 514 private static BigInteger rescale(BigInteger bi, int deltaScale) { 515 if (deltaScale == 0) 516 return bi; 517 if (deltaScale > 0) { 518 for (int i = 0; i < deltaScale; i++) 520 bi = bi.multiply(BigIntegerDecimal.TEN); 521 522 } else if (deltaScale < 0) { 523 for (int i = deltaScale; i < 0; i++) 525 bi = bi.divide(BigIntegerDecimal.TEN); 526 } 527 return bi; 528 } 529 532 public String toString() 533 { 534 if (isNull()) 535 return "NULL"; 536 else 537 return getString(); 538 } 539 } 540 | Popular Tags |